前言
关于微信小程序中父子组件的创建、传值,以及涉及到的组件生命周期。
使用组件的优点
组件的使用可以提高开发效率并确保功能在各个页面上的应用和修改的一致性。
例如,对于一些重复的功能,比如顶部导航栏或评论区,将其提炼成组件后,我们只需要在不同的页面中引用该组件,而无需重复编写相同的代码。这样能够减少代码量,提高代码的可维护性。
当需要修改这些功能时,只需在组件定义的地方进行修改,即可实现所有引用该组件的页面都得到更新,避免了在每个页面单独修改的麻烦。
正文
创建与基本使用
1.1 创建组件
组件一般创建在components文件夹下。
首先在components中新建一个文件夹,在此文件夹上右击选择新建component选项(也可以自己新建page,再将对应生成的四个子文件移入components中新建的组件文件夹中),建好的目录结构如下
1.2 使用组件->在父页面或者父组件的json文件里注册子组件
{
"usingComponents": {
"topNav": "/components/topNav/topnav"
}
}
1.3 在父页面或者父组件上应用组件
<!-- 父组件中 -->
<view class="container">
<!-- 顶部菜单 -->
<topNav></topNav>
</view>
相互传值或调用方法
上面的例子只是基础的用法,不涉及到父子组件之间的通信。
父子组件之间的通信包括:
父组件传值给子组件、子组件传值给父组件、父组件调用子组件的方法、子组件调用父组件的方法。
1.父组件传值给子组件
这个是最简单也最常用的,主要就是注意子组件中使用properties去接收就好了
- 父组件传值:
- childValue 是子组件用来接收父组件传递的值
- parentValue 是父组件传递给子组件的值。
// 父组件.wxml
<text>这是父组件Component</text>
<view>
<ChildComponent childValue="{{parentValue}}"></ChildComponent>
</view>
// 父组件.js
Page({
data: { parentValue : 'Parent'}
})
- 子组件接收与使用:
// 子组件.js
// 在子组件中声明要接收的数据类型
Component({
properties: {
childValue: String, // String代表接收的参数类型
}
})
//使用父组件传递过来的数据:
// 子组件.wxml
<text>我是子组件ChildComponent</text>
<view>父组件传递过来的数据:{{childValue}}</view>
这样子组件就可以接收到父组件传递过来的值。
2.子组件传值给父组件
这个相对复杂一些。
使用 triggerEvent() 方法,用法类似于 Vue 中的 $emit(),关键代码:
this.triggerEvent(‘myevent’, value) myevent是对应父组件中接收的方法
- 给子组件自定义一个事件,并且传值
// 子组件.wxml
<view class="childContent">
<text>我是子组件ChildComponent</text>
<button type="primary" bindtap="handleTap">给父组件传值</button>
</view>
// 子组件.js
methods: {
handleTap() {
// 定义要传递的数据
let value = "ChildValue"
// 触发绑定事件, myevent为绑定的父组件中的事件名
this.triggerEvent('myevent', value)
},
}
- 为父组件中引入的子组件绑定事件
// 父组件.wxml
<view class="parentContent">
<text>这是父组件Component</text>
<view>
// 绑定子组件中`triggerEvent()`对应的事件方法
<ChildComponent bindmyevent="myevent"></ChildComponent>
</view>
<view>父组件:子组件传递过来的数据 {{ParentValue}}</view>
</view>
//接收子组件传递过来的内容
// 父组件.js
methods: {
myevent(e) {
// 这里通过 e 就可以接收子组件传过来的内容了
console.log(e.detail)
this.setData({
ParentValue: e.detail
})
}
}
3.父组件调用子组件方法
通过给子组件绑定 id 或 class 选择器,在父组件里调用 this.selectComponent 获取子组件的实例对象,就可以调用子组件中的方法。
其实就是获取到了子组件的实例对象,那可以调用它的方法,其实也可以获取它的属性了。
// 子组件.js
methods: {
Foo() {
console.log("子组件的方法");
}
}
// 父组件.wxml
<view class="parentContent">
<text>这是父组件Component</text>
<view>
<ChildComponent class="ChildEvent"></ChildComponent>
</view>
<button type="primary" bindtap="ChildFoo">父组件的按钮</button>
</view>
// 父组件.js
methods: {
// 父组件点击事件,调用子组件方法
ChildFoo() {
// 获取子组件的实例,可以提前获取
let Child = this.selectComponent('.ChildEvent');
// 调用子组件中定义的方法Foo()
Child.Foo();
}
}
4. 子组件调用父组件方法
子组件通过 this.triggerEvent() 来调用父组件的方法。
在父组件引入的子组件上添加事件与方法名:
ChildFun是子组件中的方法名,ParentFun是父组件中的方法名;
我们通过子组件的ChildFun来调用父组件的ParentFun。
// 父组件.wxml
<view>
<ChildComponent bind:ChildFun="ParentFun"></ChildComponent>
</view>
在父组件中定义方法:
// 父组件.js
methods: {
ParentFun() {
console.log('父组件的方法');
}
}
在子组件中添加了一个点击事件,当用户触发点击事件clickParent()的时候,会执行子组件调用父组件:
// 子组件.js
methods: {
clickParent() {
this.triggerEvent('ChildFun' , )
}
}
点击后,子组件就会执行在父组件中的ParentFun()。
注意:this.triggerEvent(‘父组件中子组件上绑定的事件名’ , 参数(可选))
后面的参数根据父组件的方法进行填写。
如果父组件没有接收参数, 则空着不写,如果接收一个参数就写一个,两个参数传入两个值。
总结
简单总结:
- 父组件传值给子组件:子组件properties接收
- 子组件传值给父组件:子组件this.triggerEvent()激发传给父组件
- 父组件调用子组件的方法:父组件使用this.selectComponent 获取子组件的实例对象
- 子组件调用父组件的方法:子组件this.triggerEvent()激发传给父组件
可以看出来如果是子组件要想与父组件通信,无论是传参还是调用方法,都可以通过this.triggerEvent()实现。
传参也只是调用方法的一种特殊情况而已。主要看父组件中的调用的方法是如何使用这个参数的。
组件生命周期
具体可查看微信小程序官网内容: 小程序官方组件生命周期
组件的生命周期写法:
Component({
lifetimes: {
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
},
// 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
attached: function() {
// 在组件实例进入页面节点树时执行
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
// ...
})
关于执行的顺序,可以参考微信小程序——组件生命周期这篇文章的解释。
总结:
- 小程序在挂载、初始化的时候,是从内到外(从组件到page),在卸载的时候也是从内到外的
- 页面回退时,可以触发 pageLifetimes 的 show,这个特性可用来更新组件
组件所在页面的生命周期
Component({
pageLifetimes: {
show: function() {
// 页面被展示
},
hide: function() {
// 页面被隐藏
},
resize: function(size) {
// 页面尺寸变化
}
}
})
参考
图片与创建父子组件部分内容参考微信小程序公共组件封装,父子组件之间相互传值和相互调用方法
父子组件传值通信与事件触发主要参考:微信小程序之父子组件传值通信与事件触发(最全实用总结)