本文将学习自定义组件模版的三个特性:数据绑定、多slot、抽象节点。
在自定义组件中也可像普通页面一样进行数据绑定,同样是使用{{}}
语法。这样就可以向自定义组件传递动态数据。
在自定义组件中,定义了两个text
用来显示属性propA
和propB
。
<view class="wrapper">
<view>这里是组件的内部节点</view>
<view>
<text>propA: {{propA}}</text>
</view>
<view>
<text>propB: {{propB}}</text>
</view>
<slot></slot>
</view>
属性propA
和propB
的数据类型为String,并给了一个默认值。
Component({
/**
* 组件的属性列表
*/
properties: {
propA: {
type:String,
value:"propA"
},
propB: {
type:String,
value:"propB"
}
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
页面index绑定了数据dataFieldA
和dataFieldB
。
<view>
<my-component prop-a="{{dataFieldA}}" prop-b="{{dataFieldB}}">
<!-- 这部分内容将被放置在组件 <slot> 的位置上 -->
<view>这里是插入到组件slot中的内容</view>
</my-component>
</view>
数据dataFieldA
和dataFieldB
设置相应的值。
Page({
data: {
dataFieldA: 'hello',
dataFieldB: 'sif_666'
},
onLoad: function () {
},
})
在《微信小程序开发系列-07组件》中提到了slot节点,用于承载组件使用者提供的 wxml 结构。默认情况下,一个组件的 wxml 中只能有一个 slot 。需要使用多 slot 时,需要在组件 js 中声明启用。
如果在自定义组件中使用了多个slot,那么对使用者来说,应该怎么区分不同的slot呢?用name
命令来区分不同的slot。
如果多个slot都没有用name
命名,则只有第一个slot会生效。
在组件js中,设置多slot
options: {
multipleSlots: true// 启用多slot支持
},
<view class="wrapper">
<view>这里是组件的内部节点</view>
<view>
<text>propA: {{propA}}</text>
</view>
<view>
<text>propB: {{propB}}</text>
</view>
<slot name="slot1"></slot>
<slot name="slot2"></slot>
</view>
<view>
<my-component prop-a="{{dataFieldA}}" prop-b="{{dataFieldB}}">
<!-- 这部分内容将被放置在组件 <slot> 的位置上 -->
<view slot="slot1">这里是插入到组件slot1中的内容</view>
<view slot="slot2">这里是插入到组件slot2中的内容</view>
</my-component>
</view>
自定义组件模板中的一些节点,其对应的自定义组件不是由自定义组件本身确定的,而是自定义组件的调用者确定的。这时可以把这个节点声明为“抽象节点”。(这句话读起来有点儿抽象哈,要结合例子看会比较容易理解。)
抽象节点需要先声明后使用。抽象节点在哪个组件使用,就在哪个组件声明。
例如,自定义了一个“selectable-group”组件,该组件中包含有抽象节点"selectable",那么就需要在selectable-group.json中声明抽象节点“selectable”。
{
"componentGenerics": {
"selectable": true
}
}
在使用 selectable-group 组件时,必须要指定“selectable”抽象节点具体是哪个组件:
<selectable-group generic:selectable="custom-radio" />
这样,在生成这个 selectable-group 组件的实例时,“selectable”节点会生成“custom-radio”组件实例。
注意:节点的 generic 引用 generic:xxx="yyy"
中,值 yyy
只能是静态值,不能包含数据绑定。因而抽象节点特性并不适用于动态决定节点名的场景。即“custom-radio”只能“所见即所得”,不能使用{{}}
动态绑定。
我们现在来实现一个“选框组”(selectable-group)组件,它其中可以放置单选框(custom-radio)或者复选框(custom-checkbox)。这个组件(selectable-group)可以这样编写:
<!-- selectable-group.wxml -->
<view wx:for="{{labels}}" wx:key="*this">
<label bindtap="itemTap" data-index="{{index}}">
<selectable disabled="{{false}}" selected="{{selected[index]}}"></selectable>
{{item}}
</label>
</view>
// index/selectable-group.js
Component({
data: {
labels: [1, 2, 3],
selected: [false, false, false],
},
methods: {
itemTap: function(e) {
var selected = [false, false, false];
selected[e.currentTarget.dataset.index] = true;
this.setData({
selected: selected
})
}
}
})
上述两段代码的逻辑是:每个selectable-group组件包含三个selectable节点。接下来再自定义两个组件“custom-checkbox”和“custom- radio”:
<!--custom-checkbox.wxml-->
<checkbox disabled="{{disabled}}" checked="{{selected}}"></checkbox>
// custom-checkbox.js
Component({
properties: {
disabled: Boolean,
selected: Boolean,
},
})
<!--custom-radio.wxml-->
<radio disabled="{{disabled}}" checked="{{selected}}"></radio>
// custom-radio.js
Component({
properties: {
disabled: Boolean,
selected: Boolean,
},
})
index页面:
<!--index.html-->
<view>selectable-group with custom-radio</view>
<selectable-group generic:selectable="custom-radio" />
<view>selectable-group with custom-checkbox</view>
<selectable-group generic:selectable="custom-checkbox" />
// index.json
{
"usingComponents": {
"selectable-group": "./selectable-group",
"custom-radio": "./custom-radio",
"custom-checkbox": "./custom-checkbox"
}
}
运行结果
本文学习了自定义组件模版3个特定:
标签也好、节点也好、组件也好,这些都是一些名词或术语,从表达的角度看,它们的作用是为了方便行文。对于开发者来说,重点还是要理解它们的实质含义。我个人认为,节点和组件本质上是一样的东西;在微信小程序的术语框架下,节点是一种更小的概念,而组件可以是节点也可以是节点的组合。