组件
通过 defineComponent
函数注册小程序组件
注意
defineComponent
和 definePage
的区别在于两者的 properties
不同。
- 在 defineComponent 中
properties
表示组件属性 - 在 definePage 中
properties
表示页面路径的参数
定义一个组件
setup
为入口函数,对应小程序的 attach
生命周期,setup()
返回值将会暴露给小程序模板,可以直接在模板中使用。
defineComponent({
setup(props, ctx) {
const count = ref(0)
const increment = () => {
count.value++
}
return {
count,
increment,
}
},
})
<view bindtap="increment">{{count}}</view>
组件属性 props
setup
函数的第一个参数是组件的 props
,这些属性需要在 properties
中声明。一个 setup
函数的 props
是响应式的,并且会在传入新的 props
时同步更新。
访问 Props
请注意如果你解构了 props
对象,解构出的变量将会丢失响应性。因此我们推荐通过 props.xxx
的形式来使用其中的 props。
defineComponent({
properties: {
title: String,
},
setup(props, ctx) {
console.log(props.title)
},
})
如果你确实需要解构 props
对象,或者需要将某个 prop 传到一个外部函数中并保持响应性,那么你可以使用 toRefs() 和 toRef() 这两个工具函数:
defineComponent({
setup(props) {
// 将 `props` 转为一个其中全是 ref 的对象,然后解构
const { title } = toRefs(props)
// `title` 是一个追踪着 `props.title` 的 ref
console.log(title.value)
// 或者,将 `props` 的单个属性转为一个 ref
const title = toRef(props, 'title')
},
})
properties 声明
properties
的声明和原生小程序类似,type
支持了数组并移除了 optionalTypes
。参见 🔗 properties
defineComponent({
properties: {
min: Number,
max: {
type: Number,
value: 0,
},
lastLeaf: {
// 这个属性可以是 Number 、 String 、 Boolean 三种类型中的一种
type: [Number, String, Object],
},
},
setup(props, ctx) {
console.log(props.min)
console.log(props.max)
console.log(props.lastLeaf)
},
})
属性的类型可以为 String
Number
Boolean
Object
Array
其一,也可以为 null
表示不限制类型。
多数情况下,属性最好指定一个确切的类型。这样,在 WXML 中以字面量指定属性值时,值可以获得一个确切的类型,如:
<custom-comp min="1" max="5" />
此时,由于自定义组件的对应属性被规定为 Number
类型, min 和 max 会被赋值为 1 和 5 ,而非 "1" 和 "5" ,即:
props.min === 1 // true
props.max === 5 // true
组件上下文 ctx
传入 setup
函数的第二个参数是一个组件上下文
对象,与原生小程序 Component 实例一致。
defineComponent({
setup(props, ctx) {
// 组件的文件路径
console.log(ctx.is)
// 节点 dataset
console.log(ctx.dataset)
// 选择器
console.log(ctx.createSelectorQuery)
// 触发事件(函数,等价于 triggerEvent)
console.log(ctx.triggerEvent)
// 动画(函数)
console.log(ctx.animate)
},
})
该上下文对象是非响应式的,可以安全地解构:
defineComponent({
setup(props, { dataset, triggerEvent }) {
...
}
})
注意
setup()
中没有 this
,ctx
包含了当前实例所有可用属性和方法。
生命周期
Rubic
导出了一系列组合式 API 来注册生命周期钩子。它们的命名和 Page 原始生命周期一致。
这些函数接受一个回调,该回调的参数与对应的生命周期一致,当钩子被实例调用时,该回调将被执行。
import { defineComponent, onDetached } from 'Rubic'
defineComponent({
setup(query, ctx) {
onDetached(() => {
console.log('onDetached')
})
},
})
且 onXXX
函数都能被多次调用,依赖返回值的将会使用最后一次的返回值。
import { defineComponent, onReady } from 'Rubic'
defineComponent({
setup(query, ctx) {
onReady(() => {
console.log('onReady 1')
})
// 使用最后一次调用的返回值
onReady(() => {
console.log('onReady 2')
})
},
})
Component 生命周期对应关系
defineComponent
中可以用的生命周期注册函数以及对应关系如下:
Rubic
->原生 Component
setup
->lifetimes -> attached
onMoved
->lifetimes -> moved
onDetached
->lifetimes -> detached
onReady
->lifetimes -> ready
onError
->lifetimes -> error
onShow
->pageLifetimes -> show
onHide
->pageLifetimes -> hide
onResize
->pageLifetimes -> resize
其他选项
defineComponent
额外支持原生小程序的一些其他选项,以应对复杂场景。
behaviors
defineComponent 同样支持 behaviors
,参见 🔗 behaviors
defineComponent({
behaviors: [],
setup(props, ctx) {},
})
externalClasses
组件接受的外部样式类,参见 🔗 外部样式类
defineComponent({
externalClasses: ['my-class'],
})
options
组件选项,同 🔗 Component 构造器 中的 options
。
multipleSlots
boolean启用多 slot 支持,参见 🔗 组件 wxml 的 slot
virtualHost
boolean虚拟化组件节点,参见 🔗 虚拟化组件节点
styleIsolation
'isolated' | 'apply-shared' | 'shared'组件样式隔离,参见 🔗 组件样式隔离
defineComponent({
options: {
multipleSlots: true,
virtualHost: true,
styleIsolation: 'apply-shared',
},
setup(props, ctx) {},
})
relations
组件间关系定义,参见 🔗 组件间关系
/* 组件 custom-component.js */
defineComponent({
relations: {
'./custom-li': {
type: 'child', // 关联的目标节点应为子节点
linked: function (target) {
// 每次有 custom-li 被插入时执行,target是该节点实例对象,触发在该节点 attached 生命周期之后
},
linkChanged: function (target) {
// 每次有 custom-li 被移动后执行,target是该节点实例对象,触发在该节点 moved 生命周期之后
},
unlinked: function (target) {
// 每次有 custom-li 被移除时执行,target是该节点实例对象,触发在该节点 detached 生命周期之后
},
},
},
})