目录
一、自定义组件的数据监听器-纯数据字段
1.数据监听器的简单例子
在组件data中定义num,点击按钮时通过函数addNum函数num自增1,通过监听器来监听num是否发生改变。
<!--components/test01/test01.wxml-->
<view class="textBox">{{num}}</view>
<button bindtap="addNum" type="primary">点击num+1</button>
// components/test01/test01.js
Component({
/**
* 组件的初始数据
*/
data: {
num:0
},
/**
* 组件的方法列表
*/
methods: {
addNum(){
this.setData({
num:this.data.num + 1
})
}
},
// 定义数据监听器
observers:{
"num":function(){ //:function可省略
console.log("监听到num发生改变");
}
}
})
如果需要监听多个相同数据类型的变化,如num1,num2,num3等,可用逗号隔开:
observers:{
"num1, num2, num3":function(){
console.log("监听到num发生改变");
}
}
可通过function的形参来监听三个 num值的变化:
<!--components/test01/test01.wxml-->
<view class="textBox">{{num1}}</view>
<view class="textBox">{{num2}}</view>
<view class="textBox">{{num3}}</view>
<button bindtap="addNum1" type="primary">点击num1</button>
<button bindtap="addNum2" type="primary">点击num2</button>
<button bindtap="addNum3" type="primary">点击num3</button>
// components/test01/test01.js
Component({
/**
* 组件的初始数据
*/
data: {
num1: 0,
num2: 0,
num3: 0,
},
/**
* 组件的方法列表
*/
methods: {
addNum1(){
this.setData({
num1:this.data.num1 + 1
})
},
addNum2(){
this.setData({
num2:this.data.num2 + 1
})
},
addNum3(){
this.setData({
num3:this.data.num3 + 1
})
}
},
// 定义数据监听器
observers:{
"num1, num2, num3":function(newVal1, newVal2, newVal3){
console.log(newVal1, newVal2, newVal3);
}
}
})
监听对象:
// components/test01/test01.js
Component({
/**
* 组件的初始数据
*/
data: {
obj:{
name:"罗栎洵",
age:18
}
},
/**
* 组件的方法列表
*/
methods: {
setObj(){
this.setData({
"obj.name":"勒布朗"
})
}
},
// 定义数据监听器
observers:{
"obj.name":function(newVal){
console.log("监听到obj.name发生变化为:");
console.log(newVal);
}
}
})
<!--components/test01/test01.wxml-->
<view class="textBox">{{obj.name}}</view>
<button bindtap="setObj" type="primary">点击</button>
注:
数据监听器监听的是当前数据是否被setData(),即使被setData后的数据与之前一样,也认为数据被修改了,数据监听器也会被触发。
数据监听器的处理函数中,不要修改本身监听的数据字段,否则会进入死循环。
案例:通过按钮改变RGB的值(R、G、B),从而改变颜色块的颜色,监听器监听RGB是否发生变化,当这三个分量发生变化时,修改颜色的RGB值(colorRGB)。
<!--components/test02/test02.wxml-->
<view class="colorBox" style="background-color: rgb({{colorRGB}});"></view>
<view class="colorShow">{{rgb.r}} {{rgb.g}} {{rgb.b}}</view>
<button bindtap="changeR" type="primary">R</button>
<button bindtap="changeG" type="primary">G</button>
<button bindtap="changeB" type="primary">B</button>
/* components/test02/test02.wxss */
.colorBox{
height: 300rpx;
border: 1px solid;
}
.colorShow{
font-size: 100rpx;
}
// components/test02/test02.js
Component({
/**
* 组件的初始数据
*/
data: {
rgb: {
r: 0,
g: 0,
b: 0
},
colorRGB: "0,0,0"
},
/**
* 组件的方法列表
*/
methods: {
changeR() {
this.setData({
"rgb.r": this.data.rgb.r + 10 > 255 ? 255 : this.data.rgb.r + 10,
})
},
changeG() {
this.setData({
"rgb.g": this.data.rgb.g + 10 > 255 ? 255 : this.data.rgb.g + 10,
})
},
changeB() {
this.setData({
"rgb.b": this.data.rgb.b + 10 > 255 ? 255 : this.data.rgb.b + 10,
})
}
},
observers:{
"rgb.r, rgb.g, rgb.b":function(r, g, b){
this.setData({
colorRGB:`${r}, ${g}, ${b}`
})
}
}
// observers:{
// // ** 为通配符:监听rgb对象下所有的子数据
// "rgb.**":function(obj){
// this.setData({
// colorRGB:`${obj.r}, ${obj.g}, ${obj.b}`
// })
// }
// }
})
2.纯数据字段
说明:纯数据字段不渲染到wxml结构中的数据,不参与页面渲染。
优点:性能更高,运算更快。
如:
// components/test02/test02.js
options:{
// 设置所有以_开头的data数据为纯数据字段
pureDataPattern: /^_/ //正则表达式
},
二、组件的生命周期
链接: https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/lifetimes.html
1.组件的生命周期
组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发。
其中,最重要的生命周期是 created attached detached ,包含一个组件实例生命流程的最主要时间点。
组件实例刚刚被创建好时, created 生命周期被触发。此时,组件数据 this.data 就是在 Component 构造器中定义的数据 data 。 此时还不能调用 setData 。 通常情况下,这个生命周期只应该用于给组件 this 添加一些自定义属性字段。
在组件完全初始化完毕、进入页面节点树后, attached 生命周期被触发。此时, this.data 已被初始化为组件的当前值。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行。
在组件离开页面节点树后, detached 生命周期被触发。退出一个页面时,如果组件还在页面节点树中,则 detached 会被触发。
2.定义生命周期方法
生命周期方法可以直接定义在 Component 构造器的第一级参数中。
自小程序基础库版本 2.2.3 起,组件的的生命周期也可以在 lifetimes 字段 内进行声明(这是推荐的方式,其优先级最高)。
示例:当页面初步完成时,只触发created和attached,当点击按钮时isShow变为FALSE,相当于被页面移除,此时触发detached。
<!--pages/home/home.wxml-->
<button bindtap="hidden" type="primary">点击</button>
<my_test03 wx:if="{{isShow}}"></my_test03>
// pages/home/home.js
Page({
/**
* 页面的初始数据
*/
data: {
isShow:true
},
hidden(){
this.setData({
isShow:false
})
},
})
// components/test03/test03.js
Component({
lifetimes: {
created: function () {
//组件实例刚刚被创建好时, created 生命周期被触发
console.log("created");
},
attached: function () {
// 在组件实例进入页面节点树时执行
console.log("attached");
},
detached: function () {
// 在组件实例被从页面节点树移除时执行
console.log("detached");
},
},
// 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
// attached: function() {
// // 在组件实例进入页面节点树时执行
// },
// detached: function() {
// // 在组件实例被从页面节点树移除时执行
// },
// ...
})
3.组件所在页面的生命周期
说明:pageLifetimes:show、hide、resize
// components/test03/test03.js
Component({
//定义组件所在页面的生命周期
pageLifetimes:{
show(){
console.log("show:组件页面显示时触发")
},
hide(){
console.log("hide:组件页面被隐藏时触发");
},
resize(){
console.log("resize:组件页面尺寸发生改变时触发");
}
}
})
当网页初始化完成时,加载组件会触发show;当切换后台后,组件页面被隐藏,触发hide。
切后台方法:工具->工具栏管理->勾选切后台
三、插槽 slot
1.默认(单个)插槽
页面使用组件,则页面成为父组件,组件成为子组件。
默认插槽即使写很多slot标签也只会引用一个。
示例:
<!--pages/home/home.wxml-->
<my_test04>
<view>home页面引用的组件内容:即子组件标签定义的内容</view>
</my_test04>
<!--components/test04/test04.wxml-->
<view>
<!-- slot占一个空位,用于父组件填坑,接收wxml结构 -->
<!-- 单个(默认插槽):接收所有定义在子组件标签间的内容 -->
<slot></slot>
<text>这是子组件wxml内容</text>
</view>
当定义slot标签时页面效果:
当未定义slot标签时页面效果:
2.具名(多个)插槽
在子组件中定义多个slot标签,并为slot标签定义自己的名字,每一个slot标签接收同名父组件传给子组件的数据。
若子组件的slot标签未定义名字,则接收父组件中所有没有定义名字的数据;若子组件中没有未定义名字的slot标签,且父组件中存在未定义名字的数据,则该数据不会被渲染到wxml结构中。
注:使用多个插槽时需要在组件js中开启多个插槽的功能:multipleSlots
// components/test04/test04.js
Component({
options:{
multipleSlots: true // 启用多个slot插槽功能
},
})
示例:
<!--pages/home/home.wxml-->
<my_test04>
<view slot="let1">父组件填入第一个插槽的数据</view>
<view slot="let2">父组件填入第二个插槽的数据</view>
<view>home页面引用的组件内容:即子组件标签定义的内容</view>
<view>父组件填入未定义名字插槽的数据</view>
</my_test04>
<!--components/test04/test04.wxml-->
<view>
<slot name="let1"></slot>
<slot name="let2"></slot>
<slot></slot> // 该slot标签接收父组件中没有定义名字的插槽数据
</view>
当子组件没有定义slot标签时,父组件中没有名字的插槽数据将不被渲染:
3.父子组件传值
3种方法:
- 组件属性传值;
- 通过绑定事件的方式传值;
- 通过子组件实例对象的方式。
更多详情,请看下一节。。。