最近写到了一个模态框组件,要求按钮数量可调,所以我又开始作死啦,嘿嘿嘿。
由于小程序不允许在Page配置中的data字段中配置Function类型的数据(明明React就可以在props中配置函数的),以及组件和页面间通讯只能通过在<commpontName/>上添加bind:callbackName然后在组件上调用this.triggerEvent实现,所以想要动态配置一个模态框下的多个按钮变的相当麻烦。
现今小程序模块事件调用方式
// page.wxml
<component-tag-name bind:myevent="onMyEvent" />
<script>
// page.js
Page({
onMyEvent: function(e){
e.detail // 自定义组件触发事件时提供的detail对象
}
});
</script>
// component-tag-name.wxml
<button bindtap="onTap">点击这个按钮将触发“myevent”事件</button>
<script>
// component-tag-name.js
Component({
properties: {}
methods: {
onTap: function(){
var myEventDetail = {} // detail对象,提供给事件监听函数
var myEventOption = {} // 触发事件的选项
this.triggerEvent('myevent', myEventDetail, myEventOption)
}
}
});
</scrip>
我们可以看到这下尴尬了有没有。在多个自定义的按钮情况下,回调函数应该如何传入?
- 在<component-tag-name/>上写多个bind。pass,写完以后你回调也要定义多个,因为小程序bind:eventName就是绑定了个函数名,bind:eventName="callbackReducer(1)"什么的,不存在的……这么蠢的办法我们肯定是不会采用的。
- 写一个有限状态机,triggerEvent时提供相应状态。
// page.wxml
<component-tag-name btns="{{btnList}}" bind:myevent="onMyEvent" />
<script>
// page.js
const btnList = [{
name: 'BTN1',
url: '/pages/index/index',
}, {
name: 'BTN2',
callback() { // 必须使用function定义,使用箭头函数则无法绑定this
this.setData({ modalShow: false });
},
}];
const list = btnList.map(btn => btn.callback ? btn.callback : () => wx.navigateTo({ url: btn.url }));
const functionListReducer = (list) => (self, idx, ...args) => list[idx].call(self, args);
const btnCallbackList = functionListReducer(list);
Page({
data: { btnList },
onMyEvent: function({ detail: { idx } }){
btnCallbackList(this, idx);
},
});
</script>
// component-tag-name.wxml
<button
wx:for="{{btns}}"
wx:key="index"
data-idx="{{index}}"
bindtap="onTap">{{item.name}}</button>
<script>
// component-tag-name.js
Component({
properties: {
btns: {
type: Array,
value: [],
},
},
methods: {
onTap: function({ target: { dataset } }){
this.triggerEvent('myevent', dataset);
}
}
});