手机版

如何在原生微信小程序中实现数据双向绑定

时间:2021-12-10 来源:互联网 编辑:宝哥软件园 浏览:

在原生小程序的开发中,数据流是单向的,不能双向绑定。可能很容易实现与官方框架wepy的双向绑定。但是,使用原生组件开发技术,无需任何框架,就可以轻松实现双向绑定的功能!

下面是applet框架minapp中实现双向绑定的原理,Mina PP是一个完全兼容原生applet组件开发的框架。在minapp中,您只需要添加。同步到wxml模板中组件的属性名,实现双向绑定。为了解释它的原理,过程可能会复杂一点,但事实上,minapp框架已经处理了那些复杂的细节!

首先,为了双向绑定数据,应该避免太多的数据源。在数据自上而下自然流动的情况下,如果每个组件维护自己的数据,同时保持它们的数据值一致,尽管这是可以做到的,但实现过程并不简单。但是没必要说为了有一个统一的数据源,用mobx或者redux来全局管理数据,这有点像用刀杀鸡。因为双向绑定只存在于父组件和子组件之间,数据是从父组件传输到子组件的,所以父组件中的数据可以先作为数据源。每次子组件更新数据时,它都不会更新自己的内部数据。而是通过事件机制触发父组件更新其数据,父组件更新数据后,自然会将更新后的数据传递给子组件,从而实现数据的双向流动!

如何在原生的微信小程序中实现数据双向绑定(图1)

不是所有的数据都需要双向绑定,也不是所有的数据都是外部的。子组件也可以有自己的内部数据。所以这就引出了第二个问题:区分哪些数据需要双向绑定,哪些数据需要子组件维护。

任何使用过vue的人都应该知道,要在vue中实现双向绑定,需要在模板中做特殊处理。例如,要将父组件的parentAttr双向绑定到子组件的childAttr,您需要将它写入父组件的模板中:

childattr . sync=' parent tr '/但是小程序没有这么简单的语法,甚至没有像“.”这样的字符在小程序的wxml语言的属性名称中不允许。回到我们的问题,子组件需要知道哪些属性需要双向绑定,哪些属性需要自己维护。为什么不在模板中添加一个字段(syncAttrMap)来告诉子组件哪些数据集需要双向绑定呢?比如上面的例子可以用微信小程序支持的方式写:

childAttr=' { { parentAttr } } ' syncAttrMap=' childAttr=parentAttr '/!-如果同时存在多个双向绑定和无双向绑定的属性,可以写成:p1、p2分别双向绑定到子组件的c1、c2,P3单向绑定到C3-child C1=' { { P1 } ' C2=' { { P2 } ' C3=' { { P3 } } ' Synattrmap=' C1=p1c 2=P2 '/然后,我们需要处理子组件的数据更新。子组件中有两部分数据,其中一部分是内部数据。子组件可以读取syncAttrMap属性,找出哪些数据是内部数据,哪些数据是父组件的数据,可以知道对应父组件中数据的键名是什么。因为原生组件方法setData并不在乎你是内部数据还是父组件中的数据,只要你调用它更新数据,它只会更新内部数据。因此,需要实现一种新的方法来自动判断数据源,如果是内部数据,则调用setData直接;如果是双向绑定中的父组件数据,可以触发事件通知父组件更新相应的值。

所以根据上面的描述,父组件需要监听功能,子组件需要智能setData功能。如果您没有将父组件的监视器函数命名为onSyncAttrUpdate,而将子组件的智能设置数据函数命名为setDataSmart,则可以有以下代码:

//父组件组件({ methods : { OnSyncatRupdate(e)} this。SetDATa(e . detail)//子组件传来的需要更新的数据} }})!-父组件的模板-childAttr=' { { parentAttr } } ' syncAttrMap=' childAttr=parentAttr ' bind : synccattrupdate=' onsyncccattrupdate '///子组件组件({属性: {子属性:字符串,

syncAttrMap: String }, methods: { // 子组件更新数据时,只要调用此方法即可,而不是 `setData` setDataSmart(data) { // splitDataBySyncAttrMap 函数的实现过程就不说了,只是将对象拆分,大家应该都能实现 let {parentData, innerData} = splitDataBySyncAttrMap(data, this.data.syncAttrMap) // 内部数据使用 setData 更新 if (Object.keys(innerData).length) { this.setData(innerData) // setData 中还支持 callback 的回调,为了简化代码,这里不讨论 } // 双向绑定的父组件数据触发事件让父组件自己去更新 if (Object.keys(parentData).length) { this.triggerEvent('syncAttrUpdate', parentData) } } }})

到此,一个简单的双向绑定功能就完成了。但是由于子组件也有可能包含其它组件,也就是说子组件也可以是父组件,而父组件同样也 可以是子组件。所以上面的onSyncAttrUpdatesetDataSmart函数需要在每个组件中都实现,所以不防 定义一个公共对象BaseComponent来实现上面的所有功能,如:

// BaseComponentconst BaseComponent = {  properties: {    syncAttrMap: String  },  methods: {    setDataSmart() {      // ...    },    onSyncAttrUpdate() {      // ...    }  }}

然后将 BaseComponent mixin 到每个组件的对象上去就可以了;另外小程序中还有一个特殊的组件:Page,虽然 Page 和 Component 结构是两样的, 但它也应该算是一个组件,不过它一定是父组件,不可能是别的组件的子组件,所以还需要将onSyncAttrUpdate方法写了所有的 Page 定义中。 所有这些就是minapp的双向绑定的基本原理了。

等等,最后还有一件事:wxml 模板,不能让用户每次写双向绑定的时候都要写那么复杂语句吧?当然不用,minapp在编译模板时,会将模板做个简单的转化:

<child childAttr.sync="parentAttr" /><!-- 由于属性名 syncAttrMap 是固定的,所以完全可以通过编译手段,将上面的模板转成下面这个模板 --><child childAttr="{{parentAttr}}" syncAttrMap="childAttr=parentAttr" />

版权声明:如何在原生微信小程序中实现数据双向绑定是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。