小程序自定义组件 - 组件通信父传子
页面组件化后, 随即就面临组件间的通信问题, 就组件间如何传递数据的问题.
在 vue 中, 总结下来就是父组件通过 prop 属性给子组件传简单的值, 通过 slot 给子组件传 dom 等复杂数据; 反之, 子组件可通过 $emit 向父组件发射事件, 然后在父组件中处理逻辑, 达到子传父的效果.
在小程序中也基本是一样的操作, 父子组件通信也就3种方式:
- 父传子: 通过属性绑定, 父组件通过指定的属性仅能传递 json 相关的数据
- 子传父: 通过事件绑定, 子组件可向父组件传递任何数据
- 父组件获取子组件实例: 通过 this.selectComponent( ) 这基本就是 vue 中的 ref
因为之前学了 vue3, 现在来看小程序就相当于又复习了一遍基础, wx 改改就能用了, 极大降低了学习成本, 挺好的.
父传子-属性传值
以之前的 cj 组件为例, 父组件 index 页面通过 name 属性向 cj 组件传递字符串 "youge", 然后子组件显示出来.
第一步, 在父组件 index 页面的 js 中定义一个 name 数据, 并渲染在 index.wxml中.
// index.js
Page({
data: {
name: 'youge'
}
})
第二步, 在 index.wxml 中进行渲染, 并将其通过 name 属性传递给子组件 cj
<!--/pages/index/index.wxml-->
<view>
<view >父组件中, name 的值是: {{name}}</view>
<cj name="{{name}}"></cj>
</view>
第三步, 在子组件 cj 的 js 中需要通过设置一个名为 name 的属性进行接收 (当然取其它名也行的).
// components/cj/cj.js
Component({
properties: {
name: {
type: String,
value: ''
}
}
})
第四步, 在子组件的 wxml 中对属性进行渲染出来.
<!--components/cj/cj.wxml-->
<view class="cj">
<view>俺是子组件,</view>
<view>子组件中, 从父组件传递过来的 name 值是: {{name}}</view>
</view>
最后渲染的结果, 就是 第二步的主逻辑呈现, 即父组件 index 向子组件 cj 传值啦, 结果如下:
父组件中, name 的值是: youge
俺是子组件,
子组件中, 从父组件传递过来的 name 值是: youge
子组件自定义操作
子组件接收到富组件的传值后, 可以进行各种骚操作的, 这里以 cj 子组件接收父组件 index 页面 传递过来的 count 数值, 点击实现自增的效果为例:
还是依照上面的步骤, 父组件 index 页面部分:
// index.js
Page({
data: {
name: 'youge',
count: 1
}
})
<!--/pages/index/index.wxml-->
<view>
<view >父组件中, name 和 count 的值是: {{name}}, {{count}}</view>
<cj name="{{name}}" count="{{count}}"></cj>
</view>
子组件 cj 部分:
// components/cj/cj.js
Component({
properties: {
name: {
type: String,
value: ''
},
count: {
type: Number,
value: 0
}
},
methods: {
addOne() {
this.setData({
count: this.properties.count + 1
})
}
}
})
<!--components/cj/cj.wxml-->
<view class="cj">
<view>俺是子组件,</view>
<view>从父组件传递过来的 name, count 值是: {{name}}, {{count}}</view>
<button bindtap="addOne">+1</button>
<view>子组件最新的 count 值是: {{count}}</view>
</view>
可以看到在显示的时候, 通过点击 "+1" 的按钮, 子组件的值会跟着变, 而父组件并不会. 这不就是我们的父传子, 通过属性, 然后子组件拿到数据后是可读可写的. 需重点理解的是整个传值的逻辑和顺序. 这和 vue 的 prop 简直就是一模一样的. 父通过属性给子组件传递数据, 子组件通过 prop 接收, 然后再做一波逻辑处理, 最后做成渲染.