用了Vue长达2年,如果自己去实现一个双向绑定,我可能一个字母都写不出来,是时候探究一下了。

先看data里某对象的输出

 data() {return {pagination: {layout: 'prev,pager,next,jumper,sizes,->, total',pageSizes: [10, 20, 30, 40],currentPage: 1,pageSize: 10,total: 0}}},

我们可以看到对象属性都有有两个相对应的get和set方法,为什么会多出这两个方法呢?因为vue是通过Object.defineProperty()来实现数据劫持的。

问题来了,什么是Object.defineProperty()

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。注意:此方法是ES6新增的属性,而IE8不支持ES6语法 所以vue2.0不支持IE8浏览器。

关于es6新增的Object.defineProperty()方法是如何使用,可见

ES6-强大的对象方法 Object.defineProperty() - 简书

以下是本人根据别人的实例敲出来的实例子,自己动下手,加深下印象。

<script>let obj = {id: 1,pname: '小米',price: 1222}
function displayDate(){Object.defineProperty(obj, 'price', {value: 1999})console.log(obj);Object.defineProperty(obj, 'count', {value: 100})console.log(obj) Object.defineProperty(obj, 'id', {// writable修改后值是否可以被重写  默认是falsewritable: false})obj.id = 3 //重写无效console.log(obj);Object.defineProperty(obj, 'address', {value: '山东',// enumerable参数,设置是否可以被遍历 默认是false,通过该方法添加的默认都是false不会被遍历enumerable: false,// configurable参数,默认为false。不允许删除或修改configurable: true //值为false时,即为不可删除或修改})
console.log(obj)console.log(Object.keys(obj));  //取对象属性的方法,即遍历,因为address设置了不可被遍历delete obj.addressconsole.log(obj);}
</script>

结果如下

自己动手,印象果然一下就深刻了。

再来一个示例

<script>let obj = {id: 1,pname: '小米',price: 1222}
function displayDate(){Object.defineProperty(obj,'pname',{get:function(){//当读取obj的pname的属性值的时候,会触发这个函数console.log('get方法被调用了');//return 的值,就是属性值return pname;},set:function(val){//set可以接收一个参数,就是你想赋的值//当设置obj的pname的属性值的时候,会触发这个函数console.log('set方法被调用了');//可以通过下面方法赋值,text变量就是obj的text的属性值pname = val;}
})
obj.pname = '华为';
console.log(obj.pname)}
</script>

写到这里,聪明的你应该是知道如何实现VUE的双向绑定了,是的,它就是利用了2015年ES6标准的Object.defineProperty()方法。

手动实现一个VUE双向绑定,思路:用Object.defineProperty()的set值向input填充,用input的oninput事件触发set事件。代码如下。

var model = {};
Object.defineProperty(model,'txt',{get:function(){},set:function(val){var span = document.getElementsByTagName('span')[0];span.innerHTML = val;}
})
var input = document.getElementsByTagName('input')[0];input.oninput = function(){model.txt = input.value;//必然触发set函数}

至此,简易版的VUE双向绑定如何实现的大概思路就出来了,但我们的尤雨溪大神,肯定不会这样写。一个流行框架的诞生,所需技术与思想,不是我们常人所能达到的。

双向绑定的完整实现思路是:

我们已经知道实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理的。接着,我们还需要有一个指令解析器Compile,对每个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。

1.实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。

2.实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。

3.实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。

图解

1.实现一个Observer

Observer是一个数据监听器,其实现核心方法就是前文所说的Object.defineProperty( )。如果要对所有属性都进行监听的话,那么可以通过递归方法遍历所有属性值,并对其进行Object.defineProperty( )处理。如下代码,实现了一个Observer。

<script>function defineReactive(data, key, val) {observe(val); // 递归遍历所有子属性Object.defineProperty(data, key, {enumerable: true,configurable: true,get: function() {return val;},set: function(newVal) {val = newVal;console.log('属性' + key + '已经被监听了,现在值为:“' + newVal.toString() + '”');}});
}function observe(data) {if (!data || typeof data !== 'object') {return;}Object.keys(data).forEach(function(key) {defineReactive(data, key, data[key]);});
};var library = {book1: {name: ''},book2: ''
};
observe(library);
library.book1.name = 'vue权威指南'; // 属性name已经被监听了,现在值为:“vue权威指南”
library.book2 = '没有此书籍';
</script>

后继observer的改造,订阅者,解析器的实现本人就不研究了,略过就可以了,如有兴趣传送门。

总结:
在new Vue的时候,在 Observer 中通过 Object.defineProperty() 达到数据劫持,代理所有数据的 getter 和 setter 属性,在每次触发 setter 的时候,都会通过 Dep 来通知Watcher,Watcher 作为Observer数据监听器与Compile模板解析器之间的桥梁,当 Observer 监听到数据发生改变的时候,通过 Updater 来通知 Compile 更新视图,而 Compile 通过 Watcher 订阅对应数据,绑定更新函数,通过 Dep 来添加订阅者,达到双向绑定。

vue的双向绑定原理及实现_深海里搁浅的猫的博客-CSDN博客_vue实现双向数据绑定原理

Vue 是如何实现数据双向绑定的?_吖旭玲的博客-CSDN博客_vue如何实现数据双向绑

​​​​​​vue2核心对象defineProperty_明哥前端的博客-CSDN博客

ES6:Object.defineProperty方法_anyw_的博客-CSDN博客

ES6-强大的对象方法 Object.defineProperty() - 简书

Vue双向绑定是怎么实现的?相关推荐

  1. 梳理vue双向绑定的实现原理

    Vue 采用数据劫持结合发布者-订阅者模式的方式来实现数据的响应式,通过Object.defineProperty来劫持数据的setter,getter,在数据变动时发布消息给订阅者,订阅者收到消息后 ...

  2. vue双向绑定原理源码解析

    当我们学习angular或者vue的时候,其双向绑定为我们开发带来了诸多便捷,今天我们就来分析一下vue双向绑定的原理. 简易vue源码地址:https://github.com/maxlove123 ...

  3. 前端技巧|vue双向绑定原理,助你面试成功

    在面试一些大厂的时候,面试官可能会问到你vue双向数据绑定的原理是什么?有些小伙伴不知道是什么东西,这样你在面试官的眼里就大打折扣了.今天小千就来给大家介绍一下vue的双向绑定原理,千万不要错过啦. ...

  4. Vue双向绑定:原理篇(详细)

    文章目录 前言 什么是响应式 数据劫持 发布者-订阅者模式 模式简介 发布者 Observer 订阅器 dep 订阅者 Watcher 整体流程 初始化data data变为响应式数据 解析模板 收集 ...

  5. vue双向绑定原理及实现

    vue双向绑定原理及实现 一.MVC模式 二.MVVM模式 三.双向绑定原理 1.实现一个Observer 2.实现一个Watcher 3.实现一个Compile 4.实现一个MVVM 四.最后写一个 ...

  6. 【vue双向绑定原理浅析】

    vue双向绑定原理浅析 1.什么是双向绑定? ​ 所谓双向绑定,指的是vue实例中的data与其渲染的DOM元素的内容保持一致,无论谁被改变,另一方会相应的更新为相同的数据.(数据变化更新视图,视图变 ...

  7. vue双向绑定有时候不生效处理办法

    vue双向绑定有时候不生效处理办法 问题:当我们给响应式的对象新增属性时,新增的属性并不会显示到页面中:对于响应式的数组,增加元素.修改数组长度时,数组的这些变化也不会反映到页面中 <templ ...

  8. 记一次对vue双向绑定的理解

    之前有看过一次vue双向绑定原理实现相关的博客,看得似懂非懂的,然后也就搁浅了. 昨天脑海里又突然燃起了要不这块搞懂的冲动,于是乎又开始了一轮博客轰炸,综合研究了多位大神写得关于vue双向绑定的实现原 ...

  9. vue 双向绑定 getter 和 setter

    它的每个属性都有两个相对应的get和set方法,我觉的这是多此一举的,于是去网上查了查Vue双向绑定的实现原理,才发现它和Angular.js双向绑定的实现原理完全不同,Angular是用的数据脏检测 ...

最新文章

  1. flash,tornada demo
  2. 人类偏好的“可塑性”,从博弈说起
  3. RDKit | 基于RDKit和Python的阿斯利康ADME数据集分析
  4. ASP.NET中常用的js代码
  5. 解决AD 不能打开DDB文件的解决方案
  6. Android开发之通过反射获取全局的application
  7. Spring AOP知识点简介
  8. Spring的Web MVC –重定向到内存泄漏
  9. php 类加载其它类,PHP 命名空间 namespace / 类别名 use / 框架自动载入 机理的
  10. python cookie池_Python爬虫scrapy框架Cookie池(微博Cookie池)的使用
  11. 广播中等待较久出现anr问题
  12. 1086 就不告诉你 (15 分)—PAT (Basic Level) Practice (中文)
  13. Windows Terminal 关闭声音/提示音/table提示音
  14. 自清洁半导体异质结衬底
  15. 形式与政策网课ZIP解压密码
  16. QA与QC质量管理对比
  17. 太酷炫了,我用python画出了北上广深的地铁路线动态图
  18. 防水防腐保温工程专业承包资质标准
  19. 天下事以难而废者十之一,以惰而废者十之九。(南北朝 颜之推 《颜氏家训》)...
  20. 思享工具箱,各种工具汇总

热门文章

  1. new Point和new Point()
  2. R语言LDA线性判别分析
  3. 乐高机器人linux,乐高机器人作文范文4篇
  4. 网络安全工程师从0单排日记---(0)
  5. 关于5G接入网,最简单的解释
  6. 常用Stata命令(持续更新中)
  7. 创业文章:长风破浪会有时
  8. 在simulink中实现图像的读取和缩放操作
  9. 计算机讲评试卷教案,【作业批改记录检查情况总结】_教师备课、作业批改及记录、试卷批阅与讲评检查情况总结...
  10. Enigma虚拟文件打包使用说明