当前位置:   article > 正文

原生小程序实现复杂对象的双向绑定(附代码可直接食用)_小程序复杂类型双向绑定

小程序复杂类型双向绑定

        在做项目的过程中,出现了和对象数组进行双向绑定的需求,如果是使用vue的话,只需要一个v-model就解决了,但是原生小程序就不行啦,但是这都是无法难住大佬们的,这次找到了一个大佬的解决方式,趁机学习学习。

 

一、原生小程序的双向绑定

官方文档地址:简易双向绑定 | 微信开放文档 (qq.com)

1、浅读微信小程序的官方文档,可以得到

  • 好消息:从基础库 2.9.3 开始,使用model可以实现简易的双向绑定
  • 坏消息:并不支持data.a的形式,也就是说,基本类型可以,但是复杂类型是打咩的

2、基本使用

使用的方式非常简单,在value的前面加上model:就可以啦

<input model:value="{{value}}" />

3、在自定义组件中传递双向绑定

(1)现在你有一个组件了,这是一个输入框,使用双向绑定

<input model:value="{{myValue}}" />
  1. // custom-component.js
  2. Component({
  3. properties: {
  4. myValue: String
  5. }
  6. })

(2)你在使用模板的时候,只需要传入myValue的值就行

<custom-component model:my-value="{{pageValue}}" />

(3)如果你使用了setData

        setData会改变data中的数据,对应的,输入框中的数据也将会发生改变

二、实现复杂对象的双向绑定

来自Michaelfu的实现(双层对象):微信小程序实现双向绑定 - 掘)

1、实现思路

        通过输入框的输入事件,获取输入框的值,然后将这个值使用setData来进行更新。但是一个个获取值,然后使用setData更新太麻烦啦,所以将这个方法进行封装

  1. module.exports = {
  2. inputgetName(e) {
  3. // 从事件对象 e 中获取输入框的 data-name 属性值
  4. let name = e.currentTarget.dataset.name;
  5. // 用于存储更新后的数据对象
  6. let nameMap = {};
  7. // 通过判断 name 是否包含点符号 . 来确定是否存在多层级的数据绑定关系
  8. if (name.indexOf('.') !== -1) {
  9. let nameList = name.split('.');
  10. // 判断多层级的第一个属性是否存在于 this.data 中,
  11. 如果存在,将其保存到 nameMap 中,
  12. 否则创建一个空对象并保存到 nameMap
  13. if (this.data[nameList[0]]) {
  14. nameMap[nameList[0]] = this.data[nameList[0]];
  15. } else {
  16. nameMap[nameList[0]] = {};
  17. }
  18. // 将输入框的值 e.detail.value 更新到 nameMap 中
  19. nameMap[nameList[0]][nameList[1]] = e.detail.value;
  20. } else {
  21. // 单层的数据直接更改
  22. nameMap[name] = e.detail.value;
  23. }
  24. this.setData(nameMap);
  25. }
  26. };

2、使用方法

(1)为你的js找一个home,例如:我是放在了utils中,文件命名为binds.js

(2)将刚刚js代码复制进去(就是下面这个啦)

  1. module.exports = {
  2. inputgetName(e) {
  3. // 从事件对象 e 中获取输入框的 data-name 属性值
  4. let name = e.currentTarget.dataset.name;
  5. // 用于存储更新后的数据对象
  6. let nameMap = {};
  7. // 通过判断 name 是否包含点符号 . 来确定是否存在多层级的数据绑定关系
  8. if (name.indexOf('.') !== -1) {
  9. let nameList = name.split('.');
  10. // 判断多层级的第一个属性是否存在于 this.data 中,
  11. 如果存在,将其保存到 nameMap 中,
  12. 否则创建一个空对象并保存到 nameMap
  13. if (this.data[nameList[0]]) {
  14. nameMap[nameList[0]] = this.data[nameList[0]];
  15. } else {
  16. nameMap[nameList[0]] = {};
  17. }
  18. // 将输入框的值 e.detail.value 更新到 nameMap 中
  19. nameMap[nameList[0]][nameList[1]] = e.detail.value;
  20. } else {
  21. // 单层的数据直接更改
  22. nameMap[name] = e.detail.value;
  23. }
  24. this.setData(nameMap);
  25. }
  26. };

(3)在需要用到双向绑定的页面中引用

js文件:

  1. // 引用公共app.js公共内容
  2. var app = getApp();
  3. // 引入双向绑定js
  4. var binds = require('../../../utils/binds')

xml文件:


注意:控件需要bindinput绑定inputgetName方法,data-name属性也要与需要操作的变量匹配,否则会失效,这样就完成了。

三、扩展

        上面的方式几乎可以满足大多数的场景啦,如果是多层嵌套的情况,可以将js文件的代码替换为下面的:(注明:由于时间原因还没来得及测试这段代码,谨慎使用嗷)

  1. module.exports = {
  2. inputgetName(e) {
  3. // 从事件对象 e 中获取输入框的 data-name 属性值
  4. let name = e.currentTarget.dataset.name;
  5. // 用于存储更新后的数据对象
  6. let nameMap = {};
  7. // 通过判断 name 是否包含点符号 . 来确定是否存在多层级的数据绑定关系
  8. if (name.indexOf('.') !== -1) {
  9. let nameList = name.split('.');
  10. // 判断多层级的第一个属性是否存在于 this.data 中,如果存在,将其保存到 nameMap 中,否则创建一个空对象并保存到 nameMap
  11. if (this.data[nameList[0]]) {
  12. nameMap[nameList[0]] = this.data[nameList[0]];
  13. } else {
  14. nameMap[nameList[0]] = {};
  15. }
  16. // 将输入框的值 e.detail.value 更新到 nameMap 中
  17. nameMap[nameList[0]][nameList[1]] = e.detail.value;
  18. } else {
  19. // 单层的数据直接更改
  20. nameMap[name] = e.detail.value;
  21. }
  22. this.setData(nameMap);
  23. }
  24. };

四、总结

        以上是我的个人浅薄的见解,如果有问题请您指出~ 如果您读完本文有未解决的疑惑,可以在下方评论,我们一起解决。如果这篇文章对您有帮助,请点个赞给博主一点鼓励。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/503439
推荐阅读
相关标签
  

闽ICP备14008679号