组件可以定义一些属性,用来接收组件使用者传入的值。组件的使用者可以在 WXML 节点中指定这些属性对应的值。
定义属性
使用 Definition 形式定义属性,写法如下:
export default Component({
properties: {
fooProp: {
type: String,
value: '',
},
},
})
使用 Chaining 形式定义属性,写法如下:
export default Component()
.property('fooProp', {
type: String,
value: '',
})
.register()
上面的例子中定义了 fooProp 属性,定义时提供的 type 表示属性类型,value 表示初始值。
定义好属性之后,组件的使用者就可以在 WXML 节点中指定属性对应的值了,比如在页面中可以这样写:
<!-- page/index/index.wxml -->
<custom-component foo-prop="bar" />
在 WXML 中,驼峰写法的属性名可以换成连字符写法(当然也可以继续使用驼峰写法)。
给组件属性命名时,需要注意以下几点:
- 属性名不能和 data 数据字段重名;
idclassstyleslot是 WXML 的保留属性,虽然可以设为组件属性,但无法在 WXML 中对它们赋值;dataXxx这样的属性名也无法在 WXML 中对它们赋值,因为data-xxx=""会被视为 dataset。
属性类型与简化定义
属性支持下表中列出的类型。
| 类型 | 默认值 | 说明 |
|---|---|---|
String | '' | 字符串 |
Number | | 数值 |
Boolean | false | 布尔值 |
Object | null | 对象 |
Array | [] | 数组 |
Function | function () {} | 函数 |
null | null | 表示属性支持任意类型 |
Function类型仅 glass-easel 组件框架支持。在 exparser 组件框架中不能传递函数类型的属性,但可以将函数作为Object类型中的一个字段来传递。
如果一个属性的初始值 value 和它的类型默认值相同,就可以把属性定义简写为 type 本身,例如:
export default Component({
properties: {
fooProp: String,
},
})
export default Component()
.property('fooProp', String)
.register()
初始值和默认值
初始值 指的是一个属性没有被指定值时所具有的值。
默认值 指的是一个属性没有被指定值时所具有的值,或者当属性被赋予非法值时,用来代替非法值的那个属性值。仅 glass-easel 组件框架支持。默认值需要使用一个函数来指定,写法如下:
export default Component({
properties: {
fooProp: {
type: String,
default: () => 'DEFAULT',
},
},
})
export default Component()
.property('fooProp', {
type: String,
value: () => 'DEFAULT',
})
.register()
如果指定了默认值 default,就不能再指定初始值 value 了。
属性值类型转换
在 WXML 中为一个属性指定值时,会自动进行类型转换;如果转换失败,就会被视为非法值(这时会使用默认值来代替)。type 为 null 的属性不会进行类型转换。
举个例子,如果 custom-component 组件的 num-prop 属性是 Number 类型的,而在使用者的 WXML 中这样写:
<custom-component num-prop="1" />
这种情况下,num 属性会接收到数值 1。
布尔类型属性值转换
对于 Boolean 类型的属性,如果在 WXML 中只写了属性名而没有指定值,会自动把它的值设为 true。
<custom-component bool-prop />
<!-- 等价于 -->
<custom-component bool-prop="ANY" />
<!-- 等价于 -->
<custom-component bool-prop="{{true}}" />
如果想把它的值设为 false,就必须使用数据绑定写法,例如:
<custom-component bool-prop="{{false}}" />
对象、数组类型属性值转换
对象和数组类型的属性只能使用数据绑定写法,例如:
<custom-component array-prop="{{ [1, 2] }}" object-prop="{{ { a: 1, b: 2 } }}" />
在 glass-easel 组件框架中,绑定对象时外层的花括号可以省略:
<custom-component object-prop="{{ a: 1, b: 2 }}" />
可选类型
如果一个属性可能接受多种类型的值,可以用 optionalTypes 为它附加多个类型。例如:
export default Component({
properties: {
fooProp: {
type: String,
optionalTypes: [String, Boolean],
},
},
})
export default Component()
.property('fooProp', {
type: Number,
optionalTypes: [String, Boolean],
})
.register()
使用 TypeScript 指定对象类型
使用 TypeScript 时,对于 type 为 Array 或 Object 的属性,会根据它初始值、默认值的类型作为这个属性字段的具体类型,来进行类型推断。
这时,可以通过 as 来指定具体类型:
export default Component()
.property('objectProp', {
type: Object,
value: {} as {
foo?: number
bar?: string
},
})
.register()
属性值变化监听器
属性值可以指定一个 observer,当属性值发生变化时,会调用这个函数。
export default Component()
.property('foo', {
type: String,
observer(newVal, oldVal) {
// 属性值变化后触发
},
})
.register()
如果需要在 observer 中同步执行 setData 等更新操作,更推荐使用数据监听器,因为通常它有更好的性能。
对于 type 为 Object 或 Array 的属性,如果通过该组件自身的 this.setData 来改变属性值的一个子字段,则依旧会触发属性 observer,且 observer 接收到的 newVal 是变化的那个子字段的值。
属性值比较器
仅 glass-easel 组件框架支持。
每当组件的使用者进行更新时,组件框架需要判断它使用的每个子组件是不是被更新了。框架的判断方法是,对比每个属性值,如果属性值不一样,就认为子组件被更新了。如果子组件被更新了,就会产生一定的更新开销。
对于子组件属性是数值、字符串、布尔值等基本类型时,框架可以直接对比它们的值。但对于对象、数组这样的值,框架难以比较,常常将它们直接视为被更新了。
这时可以通过 comparer 来指定一个属性值比较函数,避免不必要的更新、提升整体性能。如果 comparer 返回真,表示属性值变化了、组件需要更新。例如:
export default Component()
.property('objectProp', {
type: Object,
comparer(newValue, oldValue) {
return newValue.foo !== oldValue.foo || newValue.bar !== oldValue.bar
},
})
.register()
页面根组件的属性值
对于页面根组件,属性值会从页面的 query 参数中获取(参数值会被自动 URL decode)。例如:
// pages/index/index.js
export default Component()
.property('strProp', String)
.property('numProp', Number)
.register()
如果页面以 pages/index/index?strProp=foo&numProp=1 打开,那么 strProp 会被赋值 'foo',numProp 会被赋值 1。
由于 query 参数是字符串,页面根组件的属性值应当是 String 或 Number 类型的。






