前言

在微信小程序的组件通信中有3种方式:

  1. 属性绑定

    • 用于父组件向子组件的指定属性设置数据,但仅能设置JSON兼容的格式数据
  2. 事件绑定

    • 用于子组件向父组件传递数据,可以传递任意数据
  3. 获取组件实例

    • 父组件还可以通过this.selectComponent()获取子组件实例对象
    • 这样就可以直接访问子组件的任意数据和方法

总而言之也就是父传子和子传父两种,这是核心知识但比较绕,于是写篇博客记录下方便之后的使用和记忆。

属性绑定(父传子)

准备例子

此时我们有一个子组件test5(components)和一个父组件home(pages),在父组件定义了一个按钮和事件bindtap(),每当点击按钮时,count的值会被动态+1,现在我们需要将该count值传入子组件test5中,让按钮点击时两个页面的count都动态+1

子组件:

1
<view>{{count}}</view>

父组件:

1
2
3
4
<view>父组件中count值是:{{count}}</view>
<view>------------------------------</view>
<my-test5></my-test5>
<button bindtap="btnAdd">+1</button>
1
2
3
4
5
6
7
8
data: {
count: 0
},
btnAdd(){
this.setData({
count:this.data.count + 1
})
},

此时页面的效果:

image-20230526175003759

这时候点击按钮只有父组件的count会+1,因为子组件中没有定义count这个值,我们可以通过properties结点给子组件传入count

test5.jsComponent下添加properties:

1
2
3
properties: {
count:Number
}

count的形式也可以为一个对象如:

1
2
3
4
5
6
properties: {
count: {
type: Number,
value: 0
}
}

这里的value是给传入的count设置一个默认值,例子中的count随父组件动态变化,不需要默认值,所以这里简写为数据类型的形式就行。

随后在home页面的组件标签中添加属性count="{{count}}"

1
2
3
4
<view>父组件中count值是:{{count}}</view>
<view>------------------------------</view>
<my-test5 count="{{count}}"></my-test5>
<button bindtap="btnAdd">+1</button>

这样就完成了父组件给子组件传值。


事件绑定(子传父)

准备例子

取上述例子,将按钮和方法都移到子组件中,此时子组件中定义了count及其方法而父组件没有,我们需要将子组件的count传入父组件

注意:compnents页面的方法只能写在methods中

注意:

子组件:

1
2
<view>{{count}}</view>
<button bindtap="btnAdd">+1</button>
1
2
3
4
5
6
7
8
9
10
data: {
count:0
},
methods: {
btnAdd(){
this.setData({
count:this.data.count + 1
})
},
}

父组件:

1
2
3
<view>父组件中count值是:{{count}}</view>
<view>------------------------------</view>
<my-test5 count="{{count}}"></my-test5>
  1. 父组件js文件定义一个自定义方法syncCount()

    1
    2
    3
    4
    5
    6
    data: {
    count: 0
    },
    syncCount(){
    console.log('sycnCount')
    }
  2. 改写父组件wxml,添加自定义事件的函数引用:

    bind:sync="syncCount"中的sync是自定义事件的名称

    1
    2
    3
    <view>父组件中count值是:{{count}}</view>
    <view>------------------------------</view>
    <my-test5 count="{{count}}" bind:sync="syncCount"></my-test5>
  3. 改写子组件btnAdd()方法,使点击按钮触发btnAdd()的同时也触发自定义事件:

    this.triggerEvent()可以用于调用自定义事件,形式为this.triggerEvent(‘自定义事件名称”,{ 参数对象})

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    data: {
    count:0
    },
    methods: {
    btnAdd(){
    this.setData({
    count:this.data.count + 1
    })
    //触发自定义事件
    this.triggerEvent('sync',{value:this.data.count})
    },
    }
  4. 改写父组件js

设置一个接受参数,此时控制台打印出来的e就是当前是自定义事件sync的属性,e.detail.value就是我们通过自定义事件传入父组件的值,即当前count的值

1
2
3
syncCount(e){
console.log(e.detail.value)
}

此时,我们可以将接收到的值同步到父组件的data

1
2
3
4
5
syncCount(e){
this.setData({
count:e.detail.value
})
},

这样就可以愉快地在父组件中使用count


获取组件实例

可在父组件里调用**this. selectComponent(“id或class选择器”)**,获取子组件的实例对象,从而直接访问子组件的任意数据和方法。调用时需要传入一个选择器,例如this.selectComponent(“.my-component”)。

如果只是用于传值,该方法是不常用的。所以这里不多赘述,使用一个简单的例子来展示。

在父组件的wxml页面引用子组件,并给子组件的标签加上一个类名或一个id

1
2
<my-test5 class="customA" id="cA"></my-test5>
<button bindtap="getChild">获取子组件实例</button>

在父组件的js文件中调用getChild()

1
2
3
4
5
6
7
8
9
10
11
12
data: {
count:0
},
getChild(){
//下面的参数不能选择标签选择器'my-test5',不然返回的是null
const child = this.selectComponent('.customA')
// 或者
// const child = this.selectComponent('#cA')
child.setData({
count:child.data.count + 1
})
},

这样很轻松的就能获取到子组件中data的值

注意:selectComponent(‘选择器’)里的选择器只能选择类选择器和id选择器,如果选择标签选择器会返回null