vue使用Proxy实现双向绑定的方法示例


Posted in Javascript onMarch 20, 2019

前言:vue3.0要用Proxy来实现双向绑定,因此先来尝试一下实现方法。

1 Object.defineProperty 实现

原来vue2的实现使用Object.defineProperty,监听set,但对于数组直接下标给数组设置值监听不了。

function observe(data) {
 if (!data || typeof data !== 'object') {
   return;
 }
 // 取出所有属性遍历
 Object.keys(data).forEach(function(key) {
   defineReactive(data, key, data[key]);
 });
};

function defineReactive(data, key, val) {
 observe(val); // 监听子属性
 Object.defineProperty(data, key, {
   enumerable: true, // 可枚举
   configurable: false, // 不能再重写defineProperty
   get: function() {
     return val;
   },
   set: function(newVal) {
     console.log('-------通知订阅者--------')
     val = newVal;
   }
 });
}

2 使用Proxy实现

使用Proxy实现原理主要是new一个Proxy对象,代理你的data值,需要注意的一点是,对于数组的方法操作来说,会产生两次赋值操作,一次是添加值,一次是改变他的length值,而对于Object.defineProperty监听不到的数组下标给数组设置值,Proxy是可以监听到的。

function observe(data) {
  if (!data || typeof data !== 'object') {
    return;
  }
  // 取出所有属性遍历
  Object.keys(data).forEach(function(_k) {
    // Proxy不允许绑定在非对象上
    if (data[_k] && typeof data[_k] === 'object') {
      data[_k] = defineReactive(data[_k]);
    }
  });
}

function defineReactive(data) {
 return new Proxy(data, {
  set(target, key, value, proxy) {
    // 进行数组操作时,会进行两次set 一次数据改变,一次length改变,两次改变data的值是不变,因此不应该多分发一次消息
   if (
    Object.prototype.toString.call(data) === "[object Array]" &&
    key === "length"
   ) {
    Reflect.set(target, key, value, proxy);
    return true;
   }
   observe(data);
   Reflect.set(target, key, value, proxy);
   console.log('-------通知订阅者--------')
   return true;
  }
 });

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript学习笔记之数组的遍历和 length 属性
Nov 23 Javascript
javascript属性访问表达式用法分析
Apr 25 Javascript
学习使用bootstrap基本控件(table、form、button)
Apr 12 Javascript
JavaScript程序中的流程控制语句用法总结
May 23 Javascript
MUI 解决动态列表页图片懒加载再次加载不成功的bug问题
Apr 13 Javascript
BootStrap数据表格实例代码
Sep 13 Javascript
JS实现的简单下拉框联动功能示例
May 11 Javascript
JS中判断字符串存在和非空的方法
Sep 12 Javascript
vue自定义键盘信息、监听数据变化的方法示例【基于vm.$watch】
Mar 16 Javascript
Layui 导航默认展开和菜单栏选中高亮设置的方法
Sep 04 Javascript
vue 解决addRoutes多次添加路由重复的操作
Aug 04 Javascript
JS数组的常用方法整理
Mar 31 Javascript
vue实现可视化可拖放的自定义表单的示例代码
Mar 20 #Javascript
详解JavaScript作用域和作用域链
Mar 19 #Javascript
vue双向绑定及观察者模式详解
Mar 19 #Javascript
Vue2.0+Vux搭建一个完整的移动webApp项目的示例
Mar 19 #Javascript
在vue中使用G2图表的示例代码
Mar 19 #Javascript
Three.js中矩阵和向量的使用教程
Mar 19 #Javascript
vue+iview动态渲染表格详解
Mar 19 #Javascript
You might like
php 在文件指定行插入数据的代码
2010/05/08 PHP
phpmyadmin安装时提示:Warning: require_once(./libraries/common.inc.php)错误解决办法
2011/08/18 PHP
PHP不用第三变量交换2个变量的值的解决方法
2013/06/02 PHP
ThinkPHP采用实现三级循环代码实例
2014/07/18 PHP
php实现excel中rank函数功能的方法
2015/01/20 PHP
yii框架无限极分类的实现方法
2017/04/08 PHP
JS 容错处理代码, 屏蔽错误信息
2021/03/09 Javascript
判断输入是否为空,获得输入类型的JS代码
2013/10/30 Javascript
JQuery设置获取下拉菜单某个选项的值(比较全)
2014/08/05 Javascript
jquery简单图片切换显示效果实现方法
2015/01/14 Javascript
apply和call方法定义及apply和call方法的区别
2015/11/15 Javascript
jquery插件jquery.confirm弹出确认消息
2015/12/22 Javascript
浅谈layer的iframe弹窗给里面的标签赋值的问题
2016/11/10 Javascript
利用nvm管理多个版本的node.js与npm详解
2017/11/02 Javascript
微信小程序基于slider组件动态修改标签透明度的方法示例
2017/12/04 Javascript
vue路由--网站导航功能详解
2019/03/29 Javascript
vue+elementUI 复杂表单的验证、数据提交方案问题
2019/06/24 Javascript
详解vue中在循环中使用@mouseenter 和 @mouseleave事件闪烁问题解决方法
2020/04/07 Javascript
[02:28]DOTA2亚洲邀请赛附加赛 RECAP赛事回顾
2015/01/29 DOTA
python实现的DES加密算法和3DES加密算法实例
2015/06/03 Python
使用Django开发简单接口实现文章增删改查
2019/05/09 Python
PyCharm中代码字体大小调整方法
2019/07/29 Python
python中pygame安装过程(超级详细)
2019/08/04 Python
python检测服务器端口代码实例
2019/08/31 Python
Python3 Tkinkter + SQLite实现登录和注册界面
2019/11/19 Python
Django实现从数据库中获取到的数据转换为dict
2020/03/27 Python
美国浴缸、水槽和水龙头购物网站:Vintage Tub & Bath
2019/11/05 全球购物
在购买印度民族服饰:Soch
2020/09/15 全球购物
土木工程专业个人求职信
2013/12/05 职场文书
环境日宣传活动总结
2014/07/09 职场文书
品牌推广活动策划方案
2014/08/19 职场文书
相亲活动方案
2014/08/26 职场文书
2019让人心动的商业计划书
2019/06/27 职场文书
实习报告范文之电话客服岗位
2019/07/26 职场文书
创业计划书之熟食店
2019/10/16 职场文书
高性能跳频抗干扰宽带自组网电台
2022/02/18 无线电