组件模板和样式
收藏
我的收藏

类似于页面,自定义组件拥有自己的 ttml 模板和 ttss 样式。​

模板数据绑定​

与普通的 ttml 模板类似,可以使用数据绑定,这样就可以向子组件的属性传递动态数据。​
<!-- 引用自定义组件的页面模板 --> <view> <my-component data-a="{{ data1 }}" data-b="{{ data2 }}"></my-component> </view>
在以上例子中,组件的属性 dataAdataB 将收到页面传递的数据。页面可以通过 setData 来改变绑定的数据字段。​
注意:这样的数据绑定只能传递 JSON 兼容数据。自基础库版本 2.46.0 开始,还可以在数据中包含函数,如果需要通过属性传递函数,需要在 app.json 中配置"component2": true,并将属性类型声明为 Function。​
{ "component2": true }
Component({ properties: { funcProp: Function, }, });

插槽 slot​

在组件的 ttml 中可以包含 slot 节点,用于将组件使用者提供的 ttml内容分发到组件中的指定位置。​
<!-- 自定义组件模板 --> <view> <slot> <view>无子节点时会显示当前备用内容</view> </slot> </view>
<!-- 引用自定义组件的模板 --> <custom-component> <view>组件slot内容</view> </custom-component>

具名插槽​

需要使用多个slot 时,可以使用不同的 name 来区分。​
<!-- 自定义组件模板 --> <view class="wrapper"> <slot name="before"></slot> <view>自定义组件</view> <slot name="after"></slot> </view>
使用时,用 slot 属性来将节点插入到不同的 slot 上。​
<!-- 引用自定义组件的模板 --> <view> <custom-component> <!-- 这部分内容将被放置在组件 <slot name="before"> 的位置上 --> <view slot="before">这里是插入到组件slot name="before"中的内容</view> <!-- 这部分内容将被放置在组件 <slot name="after"> 的位置上 --> <view slot="after">这里是插入到组件slot name="after"中的内容</view> </custom-component> </view>
name属性可以传入动态值来动态设置内容被分发的位置。​
<!-- 引用自定义组件的模板 --> <custom-component> <view slot="{{slotName}}"></view> </custom-component>
Page({ data: { slotName: "before", }, onTap() { this.setData({ slotName: "after" }); }, });

作用域插槽​

自定义组件通过 slot 使用外部调用者(例如页面)的 ttml 时,只能访问外部调用者的数据。​
<!-- 自定义组件模板 --> <view> <slot></slot> </view>
<!-- 引用自定义组件的模板 --> <custom-component> <view>page data: {{y}}</view> </custom-component>
Page({ data: { y: 2 }, });
页面输出:​
page data: 2
但有些场景下,slot 的内容想要同时使用外部调用者和自定义组件的数据。这种情况下,可以使用作用域插槽访问自定义组件内部的数据。​
自定义组件通过定义 slot 属性的方式暴露组件内部数据,外部调用者(例如页面)使用组件时,通过 slot-scope 申明为作用域插槽,属性值定义临时变量名 props,即可访问到组件内部数据。​
<!-- 自定义组件模板 --> <view> <slot x="{{x}}"></slot> </view>
Component({ data: { x: 1, }, });
<!-- 引用自定义组件的模板 --> <custom-component> <view slot-scope="props"> <view>component data: {{props.x}}</view> <view>page data: {{y}}</view> </view> </custom-component>
Page({ data: { y: 2 }, });
页面输出:​
component data: 1 page data: 2

组件样式​

组件对应 ttss 文件的样式,只对组件 ttml 内的节点生效。编写组件样式时,需要注意以下几点:​
    继承样式,如 fontcolor ,会从组件外继承到组件内;​
    自定义组件节点默认会被一层 inline 元素包裹,直接在自定义组件节点上使用 padding/margin/height/width 等样式不生效,如有在自定义组件节点上直接设置上述样式的需要,请先设置为 block样式。​
<custom-component style="display:block;padding:10px;background-color:red" ></custom-component>

Fragment 组件节点​

基础库 3.5.0 及以上版本支持 ​
默认情况下,自定义组件本身的那个节点是一个“普通”的节点,使用时可以在这个节点上设置 idclassstyle 等,就如同普通的 view 组件节点一样。 ​
<!-- 页面的 TTML --> <view style="display: flex"> <!-- 默认情况下,这是一个普通的节点,设置的 style 将作用到自定义组件内部节点上 --> <custom-component style="color: blue; flex: 1">满宽的且字体是蓝色的</custom-component> </view>
这个“普通”的节点包裹了自定义组件内部的内容,但有些时候,开发者不希望存在这个“普通”的节点,而是希望样式由自定义组件本身完全决定或者自定义组件内部的第一层节点能够响应 flex 布局。 ​
这种情况下,可以启用 Fragment 组件节点来替代这个“普通”的节点:​
Component({ options: { applyFragment: true, }, });
这样,可以将 flex 放入自定义组件内: ​
<!-- 页面的 TTML --> <view style="display: flex"> <!-- 如果启用了 Fragment 组件节点,节点上设置的样式将失效,不再作用到自定义组件内部节点上 --> <custom-component style="color: blue">不是蓝色的</custom-component> </view>
<!-- custom-component.ttml --> <view style="flex: 1"> 满宽的 <slot></slot> </view>
启用 Fragment 组件节点时,需要注意以下几点: ​
    自定义组件节点上的 idclassstyle 将不再生效; ​
    自定义组件节点上绑定的事件将不再生效; ​
    getRelationNodes 获取组件间关系将不再生效; ​
    组件实例上 selectComponentselectAllComponents 异步 API 将不再生效; ​
    SJS 事件回调函数、SJS 属性监听函数中元素所在自定义组件的ComponentDescriptor 方法中,setStyleaddClass/removeClass/hasClassgetDatasettriggerEventgetComputedStylegetBoundingClientRect 将不再生效,selectComponentselectAllComponents 将更改为从根节点使用选择器选择组件实例节点。​