自定义组件
组件和页面的区别
- 组件的.json文件中需要声明"component":true属性
- 组件的.js文件中调用的是Component() 函数
- 组件的事件处理函数需要定义到methods节点中
组件的样式隔离
默认情况下,自定义组件的样式只对当前组件生效,不会影响到组件之外的UI结构
- 组件A的样式不会影响组件C的样式
- 组件A的样式不会影响小程序页面的样式
- 小程序页面的样式不会影响组件A和C的样式
好处
- 防止外界的样式影响组件内部的样式
- 防止组件的样式破坏外界的样式
组件样式隔离的注意点
- app.wxss中的全局样式对组件无效
- 只要class选择器会有样式隔离效果,id选择器、属性选择器、标签选择器不受样式隔离的影响
- 在组件和应用组件的页面中建议使用class选择器,不要使用id、属性、标签选择器!
修改组件的样式隔离选项
默认情况下,自定义组件的样式隔离特性能够防止组件内外样式互相干扰的问题。但有时,我们希望在外界能 够控制组件内部的样式,此时,可以通过 styleIsolation 修改组件的样式隔离选项
// 在组件的.js文件中新增如下配置
Component({
options: {
styleIsolation: 'isolated'
}
})
// 或在组件的.json文件中新增如下配置
{
"styleIsolation" : "isolated"
}
可选值 | 默认值 | |
isolated | 是 |
表示
启用样式隔离
,在自定义组件内外,使用 class 指定的样式将
不会相互影响
|
apply-shared | 否 |
表示
页面 wxss 样式将影响到自定义组件
,但自定义组件 wxss 中指定的样式不会影响页面
|
shared | 否 |
表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其
他设置了 apply-shared 或 shared 的自定义组件
|
数据、方法和属性
data和properties的区别
在小程序的组件中,properties 属性和 data 数据的用法相同,它们都是
可读可写
的,只不过:
⚫
data 更倾向于
存储组件的私有数据
⚫
properties 更倾向于
存储外界传递到组件中的数据
数据监听器
数据监听器用于监听和相应任何属性和数据字段的变化,从而执行特定的操作。它的作用类似于vue中的watch侦听器。在小程序组件中,数据监听器的基本语法格式如下:
Component({
observers: {
'字段A,字段B': function(字段A的新值,字段B的新值) {
// do something
},
// 监听多个属性
'rgb.r,rgb.g,rgb.b':function(r,g,b) {
// 为data中的fullColor重新赋值
fullColor: `${r},${g},${b}`
}
// 使用通配符 ** 监听对象上所有属性的变化
'rgb.**':function(obj) {
this.setData({
fullColor: `${obj.r},${obj.g},${obj.b}`
})
}
}
})
纯数据字段
纯数据字段指的是那些不用于界面渲染的data字段。
应用场景:例如有些情况下,某些 data 中的字段
既不会展示在界面上
,
也不会传递给其他组件
,仅仅在当前
组件内部使用。带有这种特性的 data 字段适合被设置为纯数据字段。
好处:纯数据字段
有助于提升页面更新的性能
。
纯数据字段的使用规则
在 Component 构造器的 options 节点中,指定
pureDataPattern
为一个
正则表达式
,字段名符合这个正则
表达式的字段将成为纯数据字段,示例代码如下
//纯数据字段的使用规则
Component({
options: {
// 指定所有 _ 开头的数据字段为纯数据字段
pureDataPattern: /^_/
},
data: {
a: true,
_b: true
}
})
组件的声明周期
组件全部的声明周期函数
生命周期函数 | 参数 | 描述说明 |
created | 无 | 在组件实例刚刚被创建时执行 |
attached | 无 | 在组件实列进入页面节点树时执行 |
ready | 无 | 在组件在视图层布局完成后执行 |
moved | 无 | 在组件实例被移动到节点树另一个位置时执行 |
detached | 无 | 在组件实列被从页面节点树移除时执行 |
error | Object Error | 每当组件方法抛出错误时执行 |
组件主要的生命周期函数
- 组件实列刚被创建好的时候,created生命周期函数会被触发
- 此时还不能调用setData
- 通常在这个生命周期函数中,之应该用于给组件的this添加一些自定义的属性字段
- 在组件完全初始化完毕、进入页面节点树后,attached生命周期函数会被触发
- 此时,this.data已经初始化完毕
- 这个生命周期很有用,绝大多数初始化的工作可以在这个时机进行(例如发请求获取初始数据)
- 在组件离开页面节点树后,detached生命周期函数会被触发
- 退出一个页面时,会触发页面内每个自定义组件的detached生命周期函数
- 此时适合做一些清理性质的工作
Component({
// 推荐用法,优先级最高
lifetimes:{
attached(){},
detached(){}
},
// 以下是旧式的定义方式
attached(){},
detached(){}
})
组件所在页面的生命周期
有时,自定义组件的行为依赖于页面状态的变化,此时就需要用到组件所在页面的生命周期。
例如:每当触发页面的show生命周期函数的时候,我们希望能够重新生成一个随机的RGB颜色值。
在自定义组件中,组件所在页面的生命周期函数右如下3个
生命周期函数 | 参数 | 描述 |
show | 无 | 组件所在的页面被展示时执行 |
hide | 无 | 组件所在的页面被隐藏时执行 |
resize | Object Size | 组件所在页面尺寸变化时执行 |
Component({
pageLifetimes: {
show: function(){},
hide: function(){},
resize: function(){}
}
})
插槽
插槽的使用类似vue,再使用多个插槽的时候,有点不同,需要设置启用多个插槽,启用方式如下
Components({
options: {
multipleSlots: true
}
})
父子组件之间通讯
1.属性绑定
用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容的数据
// 父组件的data节点
data:{
count: 0
}
// 父组件的wxml结构
<my-test count="{{count}}"></my-test>
// 子组件的properties节点
properties: {
count: Number
}
// 子组件的 wxml 结构
<text>子组件中,count值为:{{count}}</text>
2.事件绑定
用于子组件向父组件传递数据,可以传递任意数据
// 使用bind:自定义事件名称(推荐:结构清晰)
<my-test3 count="{{count}}" bind:sync="syncCont"></my-test>
// bind后面直接写上自定义事件名称
<my-test3 conut="{{count}}" bindsync="syncCount"></my-tests>
syncCount(e) {
this.setData({
count: e.detail.value
})
}
// 子组件
methods:{
addCount(){
this.setData({
count: this.properties.count + 1
})
this.triggerEvent('sync',{value: this.properties.count})
}
}
3.获取组件实例
父组件还可以通过 this.selectComponent() 获取子组件实例对象
这样就可以直接访问子组件的任意数据和方法
// 可以在父组件中调用this.selectComponent("id或class选择器"),获取子组件的实例对象,从而直接访问子组件的任意数据和方法。调用时需要传入一个选择器。例如this.selectComponent(".my-component")。
// 父组件
<my-test3 count="{{count}}" bind:sync="syncCount" class="customA" id="cA"></my-test3>
<button bindtap="getChild">获取子组件实例</button>
getChild(){
// 切记 下面的参数不能传递标签选择器 'my-test3',不然返回的时null
const child = this.selectComponent('.customA')
child.setData({count:child.properties.count + 1 })
child.addCount() // 调用子组件的 addCount 方法
}
behaviors
behaviors是小程序中,用于实现组件间代码共享的特性,类似于vue中的mixins。
每个 behavior 可以包含一组
属性
、
数据
、
生命周期函数
和
方法
。组件引用它时,它的属性、数据和方法
会被
合并到组件中
。
每个组件可以引用多个 behavior,behavior 也可以引用其它 behavior。
// 调用 Behavior()方法,创建实例对象
// 使用module.exports 将 behavior 实例对象共享出去
module.exports = Behavior({
// 属性节点
properties: {},
// 私有数据节点
data: { username: 'zs' },
// 事件处理函数和自定义方法节点
methods: {},
// 其它节点...
})
// 1. 使用 require()导入需要的自定义 behavior 模块
const myBehavior = require("../../behaviors/my-behavior")
Component({
// 将导入的behavior 实例对象,挂载到 behaviors 数组节点中,即可生效
behaviors: [myBehavior],
// 组件的其它节点
})
behavior中所有可用的节点
可用的节点 | 类型 | 是否必填 | 描述 |
properties | Objiect Map | 否 | 同组件的属性 |
data | Object | 否 | 同组件的数据 |
methods | Object | 否 | 同自定义组件的方法 |
behaviors | String Array | 否 | 引入其它的behavior |
created | Function | 否 | 生命周期函数 |
attached | Function | 否 | 生命周期函数 |
ready | Function | 否 | 生命周期函数 |
moved | Function | 否 | 生命周期函数 |
detached | Function | 否 | 生命周期函数 |
behavior中同名字段的覆盖和组合规则
-
如果有同名的属性 (properties) 或方法 (methods):
- 若组件本身有这个属性或方法,则组件的属性或方法会覆盖
behavior
中的同名属性或方法; - 若组件本身无这个属性或方法,则在组件的
behaviors
字段中定义靠后的behavior
的属性或方法会覆盖靠前的同名属性或方法; - 在 2 的基础上,若存在嵌套引用
behavior
的情况,则规则为:父 behavior
覆盖子 behavior
中的同名属性或方法。
- 若组件本身有这个属性或方法,则组件的属性或方法会覆盖
-
如果有同名的数据字段 (data):
- 若同名的数据字段都是对象类型,会进行对象合并;
- 其余情况会进行数据覆盖,覆盖规则为:组件 >
父 behavior
>子 behavior
、靠后的 behavior
>靠前的 behavior
。(优先级高的覆盖优先级低的,最大的为优先级最高)
-
生命周期函数不会相互覆盖,而是在对应触发时机被逐个调用:
- 对于不同的生命周期函数之间,遵循组件生命周期函数的执行顺序;
- 对于同种生命周期函数,遵循如下规则:
behavior
优先于组件执行;子 behavior
优先于父 behavior
执行;靠前的 behavior
优先于靠后的 behavior
执行;
- 如果同一个
behavior
被一个组件多次引用,它定义的生命周期函数只会被执行一次。