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 相关文章推荐
基于jquery的用鼠标画出可移动的div
Sep 06 Javascript
jquery 按钮状态效果 正常、移上、按下
Aug 12 Javascript
Jquery实现的一种常用高亮效果示例代码
Jan 28 Javascript
javascript的回调函数应用示例
Feb 20 Javascript
基于javascript代码实现通过点击图片显示原图片
Nov 29 Javascript
js格式化时间的方法
Dec 18 Javascript
JavaScript实现移动端页面按手机屏幕分辨率自动缩放的最强代码
Aug 18 Javascript
基于JavaScript实现评论框展开和隐藏功能
Aug 25 Javascript
详解tween.js 中文使用指南
Jan 05 Javascript
微信小程序实现富文本图片宽度自适应的方法
Jan 20 Javascript
js获取form表单中name属性的值
Feb 27 Javascript
jQuery cookie的公共方法封装和使用示例
Jun 01 jQuery
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缩放gif和png图透明背景变成黑色的解决方法
2014/10/14 PHP
PHP中trim()函数简单使用指南
2015/04/16 PHP
PHP弱类型的安全问题详细总结
2016/09/25 PHP
PHP+MySQL实现输入页码跳转到指定页面功能示例
2018/06/01 PHP
Laravel框架实现定时发布任务的方法
2018/08/16 PHP
javascript 命名空间以提高代码重用性
2008/11/13 Javascript
javascript 表格排序和表头浮动效果(扩展SortTable)
2009/04/07 Javascript
JavaScript 解析Json字符串的性能比较分析代码
2009/12/16 Javascript
javascript 动态设置已知select的option的value值的代码
2009/12/16 Javascript
jQuery UI的Dialog无法提交问题的解决方法
2011/01/11 Javascript
基于JavaScript如何实现私有成员的语法特征及私有成员的实现方式
2015/10/28 Javascript
老生常谈的跨域处理
2017/01/11 Javascript
Vue.js原理分析之observer模块详解
2017/02/17 Javascript
微信小程序 滚动到某个位置添加class效果实现代码
2017/04/19 Javascript
Vue 组件封装 并使用 NPM 发布的教程
2018/09/30 Javascript
解决iview多表头动态更改列元素发生的错误的方法
2018/11/02 Javascript
javascript读取本地文件和目录方法详解
2020/08/06 Javascript
vuejs实现下拉框菜单选择
2020/10/23 Javascript
[53:21]2014 DOTA2国际邀请赛中国区预选赛5.21 DT VS LGD-CDEC
2014/05/22 DOTA
python实现rest请求api示例
2014/04/22 Python
给Python初学者的一些编程技巧
2015/04/03 Python
Python简单获取自身外网IP的方法
2016/09/18 Python
单链表反转python实现代码示例
2018/02/08 Python
Flask框架URL管理操作示例【基于@app.route】
2018/07/23 Python
Pandas读取MySQL数据到DataFrame的方法
2018/07/25 Python
Python matplotlib通过plt.scatter画空心圆标记出特定的点方法
2018/12/13 Python
python爬虫 urllib模块url编码处理详解
2019/08/20 Python
Python实现变声器功能(萝莉音御姐音)
2019/12/05 Python
用pytorch的nn.Module构造简单全链接层实例
2020/01/14 Python
Python使用pyexecjs代码案例解析
2020/07/13 Python
Pandas之缺失数据的实现
2021/01/06 Python
Hotter Shoes英国官网:英伦风格,舒适的鞋子
2017/12/28 全球购物
西班牙土拨鼠床垫公司,感觉在云端:Marmota
2019/03/18 全球购物
大型会议策划方案
2014/05/17 职场文书
幼儿教师年度个人总结
2015/02/05 职场文书
python数字转对应中文的方法总结
2021/08/02 Python