微信小程序中实现双向绑定的实战过程
作者:军军君01
一、双向绑定
在微信小程序中如何实现双向绑定?在开始之前先介绍下什么是双向绑定,js中定义变量数据后,通过{{}}绑定到模板中,这个过程是单向绑定,即数据的更新只能是js中更新了数据,模板中跟着修改。但是如果模板中修改数据的话,js中对应的变量数据也跟着修改则为双向绑定。
1. vue2中双向绑定实现
form元素绑定:
官网说明:https://v2.cn.vuejs.org/v2/api/#v-model
主要通过v-model指令实现数据的双向绑定,实例如下:
<!-- 当选中时,`picked` 为字符串 "a" --> <input type="radio" v-model="picked" value="a"> <!-- `toggle` 为 true 或 false --> <input type="checkbox" v-model="toggle"> <!-- 当选中第一个选项时,`selected` 为字符串 "abc" --> <select v-model="selected"> <option value="abc">ABC</option> </select>
自定义组件绑定:
通过v-model进行绑定,组件中需要声明change事件以及value 的prop,数据发生变化时通过:$emit(‘change’, value)的方式实现数据变动的通知,value 的prop用于接收父组件更新参数。
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。
具体实例如下:
Vue.component('base-checkbox', { model: { prop: 'checked', event: 'change' }, props: { checked: Boolean }, template: ` <input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)" > ` })
使用的时候通过v-model进行绑定:
<base-checkbox v-model="lovingVue"></base-checkbox>
2. vue3中双向绑定实现
form元素绑定:
官网说明:https://v2.cn.vuejs.org/v2/guide/forms.html
vue3中表单元素的绑定类似于vue2,具体可参考上述链接。
你可以用 v-model 指令在表单 、 及 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
自定义组件绑定:
官网说明:https://cn.vuejs.org/guide/components/events.html#usage-with-v-model
类似vue2中的使用方式,但是有个区别是事件时‘update:modelValue’,接收的参数是’modelValue’,和vue2不太一样。
要让这个例子实际工作起来, 组件内部需要做两件事:
将内部原生 input 元素的 value attribute 绑定到 modelValue prop输入新的值时在 input 元素上触发 update:modelValue 事件
3. 小程序中简易双向绑定
官网说明:https://developers.weixin.qq.com/miniprogram/dev/framework/view/two-way-bindings.html
双向绑定时只能使用单一字段绑定,复杂的对象无法绑定:
用于双向绑定的表达式有如下限制:
只能是一个单一字段的绑定,如
<input model:value="值为 {{value}}" />
<input model:value="{{ a + b }}" />
都是非法的;目前,尚不能 data 路径,如
<input model:value="{{ a.b }}" />
这样的表达式目前暂不支持。
组件中更新数据需要通过this.setData进行更新,另注意绑定value的类型一定要对应,不然触发不了双向绑定数据的更新。
简单绑定实例如下:
父组件
<child model:value="{{value}}"></child>
Page({ /** * 页面的初始数据 */ data: { value: '测试1' }, })
{ "usingComponents": { "child":"/components/test/child" } }
子组件
<view>value内容:{{value}}</view> <button bindtap="updateValue">更新数据</button>
Component({ /** * 组件的属性列表 */ properties: { value: String }, /** * 组件的初始数据 */ data: { }, /** * 组件的方法列表 */ methods: { updateValue() { this.setData({ value: '测试222' }); } } })
二、问题
如果微信小程序中绑定的value是一个对象,使用双向绑定时会出现堆溢出的异常:
父组件:
Page({ /** * 页面的初始数据 */ data: { value: { id: 1, name: '测试1' } }, })
<child model:value="{{value}}"></child>
子组件:
/** * 组件的属性列表 */ properties: { value: Object }, /** * 组件的初始数据 */ data: { }, /** * 组件的方法列表 */ methods: { updateValue() { this.setData({ value: { id: 2, name:'测试' } }); } }
<view>value内容:{{value}}</view> <button bindtap="updateValue">更新数据</button>
异常:
VM414 WAService.js:1 RangeError: Maximum call stack size exceeded at Function.i.safeCallback (VM414 WAService.js:1) at l.<anonymous> (VM414 WAService.js:1) at c.doUpdates (VM414 WAService.js:1) at $n (VM414 WAService.js:1) at fi (VM414 WAService.js:1) at gi (VM414 WAService.js:1) at fi (VM414 WAService.js:1) at Di._updateValues (VM414 WAService.js:1) at Di.updateValues (VM414 WAService.js:1) at c._updateCb (VM414 WAService.js:1)
具体如下:
三、方案
可将对象通过JSON.stringify转换为字符串进行绑定,子组件如果需要使用对象时,使用JSON.parse进行转换即可,具体实例如下:
父组件
<child model:value="{{value}}"></child>
Page({ /** * 页面的初始数据 */ data: { value: JSON.stringify({ id: 1, name: '测试1' }) }, })
子组件
<view>value内容:{{value}}</view> <button bindtap="updateValue">更新数据</button>
// components/test/child.js Component({ /** * 组件的属性列表 */ properties: { value: String }, /** * 组件的初始数据 */ data: { }, /** * 组件的方法列表 */ methods: { updateValue() { this.setData({ value: JSON.stringify({ id: 2, name:'测试222' }) }); } } })
总结
到此这篇关于微信小程序中实现双向绑定的文章就介绍到这了,更多相关微信小程序双向绑定内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!