一.生命周期
1.页面的生命周期
- 应用声明周期
指小程序从启动->运行->销毁的过程 - 页面生命周期
每个页面的加载->渲染->销毁的过程 - 什么是生命周期函数(应用的生命周期函数,页面的生命周期函数)
是由小程序框架提供的内置函数,会伴随着生命周期,自动按插叙执行 - 应用的生命周期函数
App({
// 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
onLaunch: function () {
},
// 当小程序启动,或从后台进入前台显示,会触发 onShow
onShow: function (options) {
},
// 当小程序从前台进入后台,会触发 onHide
onHide: function () {
},
// 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
onError: function (msg) {
}
})
- 页面的生命周期 页面.js
// 生命周期函数--监听页面加载(只会调用一个)
onLoad: function (options) { // options 获取页面参数
this.getColors()
},
// 生命周期函数--监听页面初次渲染完成(只会调用一次)
wx.setNavigationBarTitle 在这里使用 动态设置当前页面的标题
onReady: function () {
// 动态设置当前页面的标题
wx.setNavigationBarTitle({
title: this.data.query.title
})
},
// 生命周期函数--监听页面显示
onShow: function () {
},
// 生命周期函数--监听页面隐藏
onHide: function () {
},
// 生命周期函数--监听页面卸载 (只会调用一次)
onUnload: function () {
},
2.组件的生命周期
在小程序组件中,最重要的生命周期函数有三个,分别是created,attached,detached.它们的各自特点如下:
- 组件实例刚好创建好的时候,created生命周期函数会被触发
1-1 此时还不能调用 setData
1-2 通常在这个生命周期函数中,只应该用于给组件的this添加一些自定义的属性字段 - 在组件完全初始化完毕,进入页面节点树后,attached 生命周期函数会被触发
2-1 此时,this.data 以被初始化完毕
2-2 这个生命周期很有用,绝大多数初始化的工作可以在这个时候进行(例如:发送请求获取初始数据) - 在组件离开页面节点树后,detached 生命周期函数会被触发
3-1 退出一个页面时,会触发页面内每个自定义组件的 detached 生命周期函数
3-2 此时适合做一些清理性质的工作
3.lifetimes 节点
在小程序组件中,生命周期函数可以直接定义在 Component 构造器的第一级参数中,可以在lifetimes 字段内进行声明 (这是推荐的方式,其优先级最高),代码如下:
Component({
// 推荐用法
lifetimes:{
attached(){ },
detached(){ }
},
// 下面是旧的定义方式
attached(){ },
detached(){ }
})
二.自定义组件
1.创建组件
- 在项目根目录中,鼠标右键,创建 components -> test 文件夹
- 在新建的 components -> test 文件夹上,鼠标右键,点击"新建 Component"
- 键入组件的名称之后回车,会自动生成组件对应的4个文件,后缀分别为 .js .json .wxml .wxss
2.引用组件
- 局部引用: 组件只能在当前被引用的页面内使用
- 全局引用: 组件可以在每个小程序页面中使用
3.局部引用组件
在页面的 .json 配置文件中引用组件的方式,叫做"局部引用".代码如下:
在 页面.json 中
{
"usingComponents": {
"my-test1":"/components/test/test"
}
}
在 页面.wxml 中
<my-test1></my-test1>
4.全局引用组件
在 app.json 全局配置文件中引用组件的方式,叫做 “全局引用”,代码如下:
在 app.json 中
{
"usingComponents": {
"my-test1":"/components/test/test"
}
}
在任何一个 .wxml 中都可以使用
<my-test1></my-test1>
5.组件和页面的区别
- 组件的 .json 文件中需要声明 “component”:true 属性
- 组件的 .js 文件中调用的是 Component() 函数
- 组件的事件处理函数需要定义到 methods 节点中
6.样式
组件样式隔离的注意点:
-
app.wxss 中的全局样式对组件无效
-
只有 class 选择器会有样式隔离效果,id选择器,属性选择器,标签选择器不受样式隔离的影响
1.修改组件的样式隔离选项
自定义组件的样式隔离特性能够防止组件内样式互相干扰的问题
在 组件.js 中
options:{
styleIsolation:'isolated'
}
在 组件.json 中
{
"component": true,
"usingComponents": {},
"styleIsolation":"isolated"
}
7.自定义组件 - 数据,方法,和属性
- methods
事件处理函数和自定义方法需要定义到methods节点中
在 组件.js 中
Component({
/**
* 组件的初始数据
*/
data: {
count:0
},
/**
* 组件的方法列表
*/
methods: {
addCount(){ // 事件处理函数
this.setData({
count:this.data.count + 1
})
this._showCount()
},
_showCount(){ // 自定义方法建议以 '-' 开头
}
}
})
- properties 属性
用来接收外界传递到组件中的数据
在 组件.js 中 组件的
/**
* 组件的属性列表
*/
properties: {
// 第一种方式: 简化方式
// max: Number
// 第二种方式: 完整的定义方式
max:{
type:Number, // 属性值的数据类型
value:10 // 属性默认值
}
}
methods: {
addCount(){ // 事件处理函数
this.setData({
count:this.data.count + 1,
max:this.properties.max + 1 // properties 同样也可以使用this.setData进行修改
})
this._showCount()
},
_showCount(){ // 自定义方法建议以 '-' 开头
}
}
// index.wxml
<!-- max 的值可以自己定义 -->
<my-test1 max="9"></my-test1>
// 组件.wxml
<view>{{max}}</view> 可以直接使用 max
- data 和 properties 属性 的区别
data 存储组件的私有数据
properties 存储外界传递到组件中的数据 - 数据监听器(observers) 相当于 vue中的watch
// 数据监听
observers:{
// n1 n2 都是 data 里面的数据
// newn1 newn2 是新值
'n1 , n2'(newn1,newn2){
this.setData({
sum:Number(newn1) + Number(newn2)
})
}
}
- 监听对象中所有属性的变化
可以使用 通配符 ** 来监听对象中所有属性的变化
data: {
rgb:{
r:0,
g:0,
b:0
},
fullColor:'0,0,0'
}
observers:{
'rgb.**':function(obj){
this.setData({
fullColor:`${obj.r},${obj.g},${obj.b}`
})
}
}
三.父子组件通信
1. 三种方式
- 属性绑定
- 用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容的数据
- 事件绑定
- 用于子组件向父组件传递数据,可以传递任意数据
- 获取组件实例
- 父组件还可以通过 this.selectComponent() 获取子组件实例对象
- 这样就可以直接访问子组件的任意数据和方法
2.属性绑定(父组件向子组件传值)
1.父组件的 .wxml
<my-test4 count="{{count}}"></my-test4>
<view>------------</view>
<view>父组件的值: {{count}}</view>
2.在 properties 写入传过来的数据 (子组件进行接收)
/**
* 组件的属性列表
*/
properties: {
count:Number
},
3.子组件的 .wxml
<view>{{count}}</view>
3.事件绑定(子组件向父组件传值)
事件绑定用于实现子向父传值,可以传递如何类型的数据.步骤如下:
- 在父组件的 .js 中,定义一个函数,这个函数即将通过自定义事件的形式,传递给子组件
- 在父组件的 .wxml 中,通过自定义事件的形式,将步骤1 中定义的函数引用,传递给子组件
- 在子组件的 .js 中,通过调用 this.triggerEvent(‘自定义事件名称’,{参数对象}),将数据发生到父组件
- 在父组件的 .js 中,通过 e.detail 获取到子组件传递过来的数据
示例代码如下:
第一步
syncCount(){
}
第二步 bind:可以自定义="syncCount" 自定义事件
<my-test4 count="{{count}}" bind:sync="syncCount"></my-test4>
<view>------------</view>
<view>父组件的值: {{count}}</view>
第三步
data: {
count:0
},
methods: {
addCount(){
this.setData({
count:this.data.count + 1
})
// 触发自定义事件,将数值同步给父组件
this.triggerEvent('sync',{value:this.data.count})
}
}
第四步
syncCount(e){
console.log(e.detail)
// e 是子组件传过来的参数
this.setData({
count:e.detail.value
})
}
4.获取组件实例
可在父组件里调用 this.selectComponent(‘id或class选择器’),获取子组件的实例对象,从而直接访问子组件的任意数据和方法.调用时需要传入一个选择器,例如 this.selectComponent(’.my-component’)
// 父组件的 .wxml
<my-test4 count="{{count}}" bind:sync="syncCount" class="customA" id="cA"></my-test4>
<view>父组件的值: {{count}}</view>
<button bindtap="getChild">获取子组件的实例对象</button>
// 父组件的 .js
getChild(){
// 注意点: 下面的参数不能传递标签选择器 'my-test4',会返回null
const child = this.selectComponent('.customA')
console.log(child)
// child.setData({ // 调用子组件的 setData 方法
// count:child.properties.count + 1
// })
// 还可以调用子组件中的方法 addCount
child.addCount()
}