vue.js源码 - 剖析observer,dep,watch三者关系 如何具体的实现数据双向绑定

2018-04-15 admin

Vue双向数据绑定的核心和基础api是Object.defineProperty,其内部真正参与数据双向绑定流程的主要有Obderver、Dep和Watcher,基于defineProperty和发布者订阅者模式,最终实现数据的双向绑定。那么Obderver、Dep和Watcher是如何具体配合工作的呢?下面就来理一理。

看此文章之前你需要对vue的双向数据绑定有一定的理解。若不了解可移步:vue.js源码解读系列 - 双向绑定具体如何初始化和工作

看到这里就当你对双向数据绑定已经有一定的理解:

提示:要看懂此篇文章你需要对vue的mvvm有一定的了解,并需要和专注的去理解,或者对照源码跟着走,不然就很难真的看懂。

在这里把双向数据绑定分为两个流程:

1、收集依赖流程:

observe -> 
walk -> 
defineReactive -> 
get -> 
dep.depend() -> 
watcher.addDep(new Dep()) -> 
watcher.newDeps.push(dep) -> 
dep.addSub(new Watcher()) -> 
dep.subs.push(watcher)

依赖收集会经过以上流程,最终watcher.newDeps数组中存放dep列表,dep.subs数组中存放watcher列表。

为什么要进行依赖收集?

new Vue({
    data(){
        return {
             name:'zane',
             sex:'男'
        }
    }
})

有上面这个data,实际上页面只使用到了name,并没有使用age,根据Object.defineProperty的转换,如果我们设置了this.sex=‘女’,那么Vue也会去执行一遍虚拟DOM的比较,这样就无形的浪费了一些性能,因此才需要做依赖收集,界面用到了就收集,没有用到就不收集。

我们跟着流程走来理一遍源码:

直接进入Object.defineProperty的get方法:

考验你闭包能力的时候到了,这个dep对象就是一个闭包。记下来我们看看dep.depend()方法的实现。

先暂停一下,上面两处都用到了 Dep.target ,我也说了它就是一个Watcher实例化对象,你是不是很想搞懂它到底在哪里赋值的呢,不急请跟着我下面的代码看看。

搞懂了Dep.target等于一个Watche对象,现在继续回到之前的思路看watcher.addDep做了什么。 就这样依赖收集的流程就走完了,是否感觉很绕。

总结:依赖收集最终在 watcher.newDeps 中push了闭包中传过来的dep对象,在dep.subs中push了初始化Vue是简历的Watcher对象,这个对象的,this.getter = expOrFn,传过来的expOrFn是后期数据更新页面渲染的核心步骤,需要沉下心来好好去理理。

2、视图更新流程:

set -> 
dep.notify() -> 
subs[i].update() -> 
watcher.run() || queueWatcher(this) -> 
watcher.get() || watcher.cb -> 
watcher.getter() -> 
vm._update() -> 
vm.__patch__()

视图更新会经过以上流程,最终调用Vue的虚拟Dom diff过程实时更新界面视图

走到此处后面我就不去跟踪了,后面会调用vm.patch 方法,进而执行虚拟DOM的diff过程实时的更新界面。

总结: 要很好的理解vue的数据双向绑定就要比较耐心,沉下心来慢慢理解,同时也需要对vue的源码有个大致的理解,不然你只会看的越来越烦躁越来越没有信心。

vue很好的利用了Object.defineProperty方法的 get和set方法,订阅者发布者的设计思路,巧妙的组织代码,值得我们很深入的去学习和理解,从而促使我们更好的去使用它。谢谢尤大的无私奉献,让我们提高了生产力,把更多的精力花到业务逻辑中去。

原文地址:https://github.com/wangweiang…

相关文章
JavaScript实现PC手机端和嵌入式滑动拼图验证码三种效果
PC和手机端网站滑动拼图验证码效果源码,同时包涵了弹出式Demo,使用ajax形式提交二次验证码所需的验证结果值,嵌入式Demo,使用表单形式提交二次验证所需的验证结果值,移动端手动实现弹出式Demo三种效果 首先要确认前端使用页面,比如...
2017-03-17
React.js编程思想
JavaScript框架层出不穷,在很多程序员看来,React.js是创建大型、快速的Web应用的最好方式。这一款由Facebook出品的JS框架,无论是在Facebook还是在Instagram中,它的表现都非常出色。 使用React.j...
2015-11-12
从2014年的发展来展望JS的未来将会如何
<font face="寰�杞�闆呴粦, Arial, sans-serif ">2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
破解前端面试(80% 应聘者不及格系列):从 闭包说起
不起眼的开始 招聘前端工程师,尤其是中高级前端工程师,扎实的 JS 基础绝对是必要条件,基础不扎实的工程师在面对前端开发中的各种问题时大概率会束手无策。在考察候选人 JS 基础的时候,我经常会提供下面这段代码,然后让候选人分析它实际运行的结...
2017-06-02
Vue.js组件tab实现选项卡切换
本文实例为大家分享了vue插件tab选项卡的具体代码,供大家参考,具体内容如下 效果图: 代码如下: <!DOCTYPE html> <html lang="en"> <head> ...
2017-03-13
JavaScript教程:JS中的原型
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。 标准方法(The Standard Way) 一直以来,我们学习的在 JavaScript 里创建对...
2015-11-12
Vue获取DOM元素样式和样式更改示例
在 vue 中用 document 获取 dom 节点进行节点样式更改的时候有可能会出现 ‘style’ is not definde的错误,这时候可以在 mounted 里用 $refs 来获取样式,并进行更改: <template...
2017-03-13
NodeJS参考手册pdf版
下载地址:Nodejs参考手册PDF版下载 ...
2015-11-12
Riot.js:不足1KB的MVP客户端框架
Riot.js是一款MVP(模型-视图-呈现)开源客户端框架,其最大的特点就是体积非常小,不足1KB,虽然体积小,但它可以帮助用户构建大规模的Web应用程序。 Riot.js是由Moot公司开发,目前最新版本为v0.9.2,遵循MIT开源许...
2016-03-11
three.js实现围绕某物体旋转
话不多说,请看代码: 可以拖动右上角观察变化 <!DOCTYPE html> <html lang="en" style="width: 100%; height:100%;"&gt...
2017-02-17
回到顶部