微信小程序 组件通信相关知识整理
1、自定义组件间通信与事件
https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html
(1)、WXML 数据绑定:用于父组件向子组件的指定属性设置数据
<!-- 父组件 index.wxml--> <view class="container"> // 子组件 <v-child propA="{{dataA}}" propB="{{dataB}}" propC="{{dataC}}"></v-child> </view> <!-- index.json--> { "usingComponents": { "v-child": "/components/child/index" } } <!-- index.js--> const app = getApp() Page({ data: { dataA: "来自父组件index的数据", dataB: true, dataC: 2300 } })
<!-- 子组件 child index.html --> <view class="content"> <view>String: {{propA}}</view> <view>Boolean: {{propB}}</view> <view>Number: {{propC}}</view> </view> <!-- 子组件 index.js --> Component({ /** * 组件的属性列表 */ properties: { propA: String, propB: Boolean, propC: Number }, /** * 组件的初始数据 */ data: { }, /** * 组件的方法列表 */ methods: { } })
页面渲染结果:
(2)、事件:用于子组件向父组件传递数据,可以传递任意数据
<!-- 子组件 event --> <!-- index.wxml --> <view class="content"> <view class="title">自定义事件</view> <button bindtap="tapclick">点击</button> </view> <!-- index.js --> Component({ /** * 组件的方法列表 */ methods: { tapclick: function(event) { let behavior = { id: 123456, name: 'Natasha', gender: 'female' } this.triggerEvent('customevent', { behavior: behavior }, {}) } } })
<!-- 父组件 index --> <!-- index.wxml --> <view class="container"> <v-event bind:customevent="onCustomEvent"></v-event> <view wx:if="{{id}}">id: {{id}}</view> <view wx:if="{{name}}">name: {{name}}</view> <view wx:if="{{gender}}">gender: {{gender}}</view> </view> <!-- index.js --> const app = getApp() Page({ onCustomEvent: function(event) { console.log(event) let id = event.detail.behavior.id, name = event.detail.behavior.name, gender = event.detail.behavior.gender this.setData({ id: id, name: name, gender: gender }) }, })
通过 triggerEvent 触发自定义事件,并把数据通过第二个参数(detail对象)传递给父组件
2、组件间代码共享 Behavior
假如多个子组件共享相同的 properties,data,methods,在每一个组件中都去重复粘贴相同的代码是完全没有必要的,这个时候可以用到 behavior
新建一个 my-behavior.js 文件
module.exports = Behavior({ behaviors: [], properties: { carModel: String, price: Number, sale: Boolean }, data: { myBehaviorData1: "eyes on me" }, attached: function() { }, methods: { myBehaviorMethod: function() { console.log("I don't have an idea to buy or not") } } })
在组件中 引用 behavior.js
<!-- js --> let myBehavior = require ("../my-behavior.js") Component({ behaviors: [myBehavior], /** * 组件的属性列表 */ properties: { }, /** * 组件的初始数据 */ data: { }, /** * 组件的方法列表 */ methods: { } }) <!-- wxml --> <view class="content"> <view>v-like component</view> <view class="title">共有data属性:</view> <view>{{myBehaviorData1}}</view> <view class="title">共有property属性:</view> <view>型号: {{carModel}}</view> <view>价格: {{price}}元</view> <view>是否折扣:{{sale}}</view> <view class="title">共有方法:</view> <button bindtap="myBehaviorMethod">button</button> </view>
例如,父组件 index.wxml 中有 v-like 和 v-movie 共用相同的代码
<!-- 父组件 index.wxml --> <view class="container"> <v-like carModel="SYLPHY" price="135000" sale="true"></v-like> <v-movie carModel="XTS" price="250000" sale="false"></v-movie> </view>
页面渲染效果
3、自定义组件的显示与隐藏
显示与隐藏可以使用 wx:if 和 hidden 来控制,二者都接受一个 Boolean 类型的值,所以传值的时候就要注意了
<!-- "false" 是一个非空字符串,所以会显示 --> <view wx:if="false">1、wx:if="false"</view> <!-- {{false == ""}}是true,空字符串被解析为false,而hidden为false时,是不会隐藏的,所以会显示 --> <view hidden="">2、hidden=""</view> <!-- 同上,wx:if 为true时才会插入到DOM节点中,此时为false,所以不会显示 --> <view wx:if="">3、wx:if=""</view> <!-- 与 1 相同,无论是字符串 "true" 还是 "false",都被解析成true,所以下面两个都会被隐藏 --> <view hidden="true">4-1、hidden="true"</view> <view hidden="false">4-2、hidden="true"</view> <!-- 以下两个都是布尔值,所以一个不被渲染到DOM中,一个被隐藏 --> <view wx:if="{{false}}">5、wx:if="{{false}}"</view> <view hidden="{{true}}">6、hidden="{{true}}"</view>
渲染结果:
按照上面的写法,避开雷区,尝试用 wx:if 和 hidden 分别来隐藏自定义组件 v-like 和 v-movie
<view class="container"> <v-like hidden="{{true}}" carModel="SYLPHY" price="135000" sale="true"></v-like> <v-movie wx:if="{{false}}" carModel="XTS" price="250000" sale="false"></v-movie> </view>
理论上,这两个自定义组件应该都不会显示,但实际上,只有 wx:if 达到了预期的效果
那为什么自定义组件 v-like 上的hidden没有起作用呢?无论 hidden="{{true}}" 还是 hidden="{{false}}" 都没办法让它隐藏,这里有一种可能就是 hidden 被当做成和 carModel,price 一样的自定义属性了
现在尝试将 hidden 当做自定义属性由父组件向子组件v-like传值,v-movie 不做修改。将 hidden 值设为 true。如果成功的话,v-like 组件将被隐藏,v-movie 组件将会显示
<!-- index.wxml --> <view class="container"> <v-like hidden="{{hidden}}" carModel="SYLPHY" price="135000" sale="true"></v-like> <v-movie wx:if="{{hidden}}" carModel="XTS" price="250000" sale="false"></v-movie> </view> <!-- index.js --> Page({ data: { dataA: "来自父组件index的数据", dataB: true, dataC: 2300, hidden: true } })
v-like 组件加上 hidden 属性
<!-- like.wxml --> <view class="content" hidden='{{hidden}}'> <view>v-like component</view> <view class="title">共有data属性:</view> <view>{{myBehaviorData1}}</view> <view class="title">共有property属性:</view> <view>型号: {{carModel}}</view> <view>价格: {{price}}元</view> <view>是否折扣:{{sale}}</view> <view class="title">共有方法:</view> <button bindtap="myBehaviorMethod">button</button> </view> <!-- like.js --> properties: { hidden: Boolean },
v-movie 不加 hidden属性
<view class="content"> <view>v-movie component</view> <view class="title">共有data属性:</view> <view>{{myBehaviorData1}}</view> <view class="title">共有property属性:</view> <view>型号: {{carModel}}</view> <view>价格: {{price}}元</view> <view>是否折扣:{{sale}}</view> <view class="title">共有方法:</view> <button bindtap="myBehaviorMethod">button</button> </view>
渲染结果:
结果和预期的一样,所以,要控制自定义组件的显示与隐藏,如果不考虑性能消耗的情况下,可以直接使用 wx:if;如果 hidden 更符合实际需求,可按如上方法来使用
示例代码:https://github.com/frwupeng517/wetchat-applet-behavior-