Vue双向数据绑定实现原理
1 访问器属性是对象中的一种特殊属性,它不能直接在对象中设置,而必须通过 defineProperty() 方法单独定义。
var obj = { };
// 为obj定义一个名为 hello 的访问器属性
Object.defineProperty(obj, "hello", {
get: function () {return sth},
set: function (val) {/* do sth */}
})
obj.hello // 可以像普通属性一样读取访问器属性
访问器属性的"值"比较特殊,读取或设置访问器属性的值,实际上是调用其内部特性:get和set函数。
obj.hello // 读取属性,就是调用get函数并返回get函数的返回值
obj.hello = "abc" // 为属性赋值,就是调用set函数,赋值其实是传参
get 和 set 方法内部的 this 都指向 obj,这意味着 get 和 set 函数可以操作对象内部的值。另外,访问器属性的会"覆盖"同名的普通属性,因为访问器属性会被优先访问,与其同名的普通属性则会被忽略。
二、极简双向绑定的实现
此例实现的效果是:随文本框输入文字的变化,span 中会同步显示相同的文字内容;在js或控制台显式的修改 obj.hello 的值,视图会相应更新。这样就实现了 model => view 以及 view => model 的双向绑定。
以上就是 Vue 实现双向绑定的基本原理。
三、分解任务
上述示例仅仅是为了说明原理。我们最终要实现的是:
首先将该任务分成几个子任务:
1、输入框以及文本节点与 data 中的数据绑定(
每次new一个vue,都调用了new selfVue函数,把el,data,methods,...作为一个对象当成参数传给selfVue函数,用Object.keys遍历data对象的每个属性,对其所有属性都进行监听,
让他们成为访问器属性,都有getter和setter方法,同时会调用observe(this.data),就是为了初始化一个监听器,监听data中的数据,然后new Compile(options.el,this)就是
初始化一个解析器,遍历其所有节点,判断是元素节点还是文本节点,如果是文本节点就直接编译,第一步初始化视图数据,第二步初始化一个订阅者(new Watcher()),并给订阅者绑定更新函数,然后订阅者就会把自己自动
添加到订阅器中,如果是元素节点,就要区分具体是什么指令,解析这些指令,如果是事件指令就给他绑定事件,如果是v-model类似的指令,就给他绑定input事件,并且完成挂载,更新视图,同时初始化
一个订阅者,并绑定更新函数
)
2、输入框内容变化时,data 中的数据同步变化。即 view => model 的变化。
(
修改输入框内容,在事件回调中修改属性值,(通过self.vm[exp]=newValue,触发selfVue中的setter去修改的)
,)
3、data 中的数据变化时,文本节点的内容同步变化。即 model => view 的变化。
(
属性变了,就触发监听器里的setter,就会触发订阅器的dep.notify(),这个函数会遍历所有
订阅者去更新,订阅者收到通知,就会执行绑定的更新函数
,)
要实现任务一,需要对 DOM 进行编译,这里有一个知识点:DocumentFragment。
八、双向绑定的实现
回顾一下,每当 new 一个 Vue,主要做了两件事:第一个是监听数据:observe(data),第二个是编译 HTML:nodeToFragement(id)。
在监听数据的过程中,会为 data 中的每一个属性生成一个主题对象 dep。
在编译 HTML 的过程中,会为每个与数据绑定相关的节点生成一个订阅者 watcher,watcher 会将自己添加到相应属性的 dep 中。
我们已经实现:修改输入框内容 => 在事件回调函数中修改属性值 => 触发属性的 set 方法。
接下来我们要实现的是:发出通知 dep.notify() => 触发订阅者的 update 方法 => 更新视图。
这里的关键逻辑是:如何将 watcher 添加到关联属性的 dep 中。
在编译 HTML 过程中,为每个与 data 关联的节点生成一个 Watcher。Watcher 函数中发生了什么呢?
首先,将自己赋给了一个全局变量 Dep.target;
其次,执行了 update 方法,进而执行了 get 方法,get 的方法读取了 vm 的访问器属性,从而触发了访问器属性的 get 方法,get 方法中将该 watcher 添加到了对应访问器属性的 dep 中;
再次,获取属性的值,然后更新视图。
最后,将 Dep.target 设为空。因为它是全局变量,也是 watcher 与 dep 关联的唯一桥梁,任何时刻都必须保证 Dep.target 只有一个值。
https://juejin.im/entry/59116fa6a0bb9f0058aaaa4c
https://github.com/DDFE/DDFE-blog/issues/7
Vue双向数据绑定实现原理的更多相关文章
- 详解 vue 双向数据绑定的原理,并实现一组双向数据绑定
1:vue 双向数据绑定的原理: Object.defineProperty是ES5新增的一个API,其作用是给对象的属性增加更多的控制Object.defineProperty(obj, prop, ...
- vue双向数据绑定的原理-object.defineProperty() 用法
有关双向数据绑定的原理 关于数据双向绑定的理解:利用了 Object.defineProperty() 这个方法重新给对象定义了新属性,在操作新属性分别为为获取属性值(调用get方法)和设置属性值(调 ...
- angular和vue双向数据绑定
angular和vue双向数据绑定的原理(重点是vue的双向绑定) 我在整理javascript高级程序设计的笔记的时候看到面向对象设计那章,讲到对象属性分为数据属性和访问器属性,我们平时用的js对象 ...
- vue实现双向数据绑定的原理
vue实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的. 在MDN上对该方法的说明是:O ...
- vue的双向数据绑定实现原理
在目前的前端面试中,vue的双向数据绑定已经成为了一个非常容易考到的点,即使不能当场写出来,至少也要能说出原理.本篇文章中我将会仿照vue写一个双向数据绑定的实例,名字就叫myVue吧.结合注释,希望 ...
- vue的双向数据绑定实现原理(简单)
如果有人问你,学vue学到了什么,那双向数据绑定,是必然要说的. 我们都知道,在vue中,使用数据双向绑定我们都知道是v-modle实现的. 实现原理是通过Object.defineProperty的 ...
- Vue双向数据绑定原理分析(转)
add by zhj: 目前组里使用的是前端技术是jQuery + Bootstrap,后端使用的Django,Flask等,模板是在后端渲染的.前后端没有分离,这种做法有几个缺点 1. 模板一般是由 ...
- vue双向绑定的原理及实现双向绑定MVVM源码分析
vue双向绑定的原理及实现双向绑定MVVM源码分析 双向数据绑定的原理是:可以将对象的属性绑定到UI,具体的说,我们有一个对象,该对象有一个name属性,当我们给这个对象name属性赋新值的时候,新值 ...
- vue 双向数据绑定的实现学习(二)- 监听器的实现
废话:上一篇https://www.cnblogs.com/adouwt/p/9928278.html 提到了vue实现的基本实现原理:Object.defineProperty() -数据劫持 和 ...
随机推荐
- noip模拟赛 Massacre at Béziers
题目背景 下发压缩包链接: https://pan.baidu.com/s/1geC4ooz 密码: 3vpt 所有的一切———所有的一切都被染成了红与黑. 翻卷的红莲烈焰舔舐着大地,释放出异抽的黑烟 ...
- hdu 4786 最小生成树与最大生成树
/* 题意 :有一些边权值为1和0,判断是否存在一个生成树使得他的总权值为一个斐波那契数. 解法:建立一个最小生成树向里面加权值为1的边替换为0的边,保证原来的联通.因为权值为1,可直接求出最大生成树 ...
- Q - Period II
For each prefix with length P of a given string S,if S[i]=S[i+P] for i in [0..SIZE(S)-p-1], then the ...
- H - Seek the Name, Seek the Fame
The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the l ...
- JEval使用实例
jeval是为为你的Java应用程序提供可增加的.高性能.数学. 布尔和函数表达式的解析和运算的高级资源包. 以下这个样例包括了JEval经常使用功能: package demo0; import ...
- 整理100道 .net面试题
前段时间,我在准备面试的时搜到的一套 net开发人员面试题,感觉比较全面,一直保存在草稿,刚在整理后台时翻了出来,干脆就发出来好了,以备不时之需. 1. .NET和C#有什么区别 答:.NET一般指 ...
- android graphic(15)—fence
为何须要fence fence怎样使用 软件实现的opengl 硬件实现的opengl 上层使用canvas画图 上层使用opengl画图 下层合成 updateTexImage doComposeS ...
- bzoj1606[Usaco2008 Dec]Hay For Sale 购买干草(01背包)
1606: [Usaco2008 Dec]Hay For Sale 购买干草 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1240 Solved: 9 ...
- Appium + python -小程序实例
from appium import webdriverfrom appium.webdriver.common.touch_action import TouchActionfrom time im ...
- Python 45 长度及颜色单位 、字体样式 、文本样式 、背景样式 、css基础选择器
一:长度及颜色单位 长度单位 px(像素) in(英寸) pt(点),一个标准的长度单位,1pt = 1/72in mm(毫米) cm ...