探寻Vue数据双向绑定的底层原理

小编我最近在研究Vue底层数据双向绑定的实现原理,目前还停留在比较肤浅的层面,先把最近的学习成果总结一下,分享给大家

什么是数据双向绑定

Vue增长趋势迅猛,很大程度上得益于他“数据双向绑定”的设计模式。所谓的双向绑定就是在数据与视图层相互映射,当数据发生变化时,相应的视图层会随之更新,相反的,如果视图层发生变化,那么相对应的数据也会随之发生变化。这也是一个典型的MVVM模型

MVVM模型

上图是一个MVVM模型的模块关系图。

图中的View为视图层,ViewModel代表逻辑控制层,Model代表数据层。

其中ViewModel作为视图层和数据层的代理,视图层变化会传递给ViewModel,数据层的变化也会传递给ViewModel,ViewModel再将变化通知给相应的数据层和视图层。

如何监测数据的变化

Vue官网关于如何检测到数据变化给出的解释是,Vue使用了Object.defineProperty方法在Vue模型初始化时,对于data进行遍历并重写他们的setter和getter方法,从而实现了数据变化的检测。由于Object.defineProperty是仅ES5才支持的方法,所以这也解释了为什么VUE对于低版本的浏览器不支持(仅支持IE8以上)。

简单回顾一下setter和getter:Object的原生方法defineProperty可以来定义Object中的一些属性,包括enumerable(是否可以被枚举)、writable(是否可写)、get(获取属性值时调用的方法)、set(设定属性值调用的方法)。

可以看MDN中给出的例子来进一步理解setter和getter的运行原理。

有了getter/setter方法,Vue就可以对于data中的数据进行监测了(Observe)。知道了这一点,你就会明白为什么Vue 不允许在已经创建的实例上动态添加新的根级响应式属性。

如何检测视图层的变化

视图层的变化很容易监测到,可以直接利用浏览器的事件触发机制。Vue实现了一个指令编译器Compiler来对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数。

如何实现双向绑定

通过上面的讲解,我们已经知道Vue是如何检测到数据层和视图层的变化了,那么Vue是如何将二者的变化进行相互响应式的更新呢?

Vue自身实现一个Watcher,作为连接Observer和Compile的桥梁。而数据层的Observe和视图层的Compile都是基于观察者模式实现的,再加上Watcher这个中间桥梁,Vue实例能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图

总结

Vue的数据双向绑定是基于Object.defineProperty方法的“数据劫持”和观察者模式而开发的。本篇并没有深入研究Observe、Compiler、Watcher的底层代码,只是从软件分层和核心思路来讨论Vue的实现原理,事实上Vue还有很多很多高深的算法和内部优化逻辑,如异步更新队列和Virtual DOM等等。今后有机会再与大家分享这些内容。

原文发布于微信公众号 - 较真的前端(gh_7af41a2be77e)

原文发表时间:2017-09-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏菩提树下的杨过

Flash/Flex学习笔记(15):FMS 3.5之远程共享对象(Remote Shared Object)

FMS中的“远程共享对象”可以让多个Client端的flash应用共享同一个全局对象,并且当客户端中的任何一个改变该对象时,系统会自动将该对象回发到FMS服务器...

2108
来自专栏云瓣

React16.x特性剪辑

在 16 之前的版本的渲染过程可以想象成一次性潜水 30 米,在这期间做不了其它事情(Stack Reconciler);

1032
来自专栏编程

从 0到1,开发一个动画库(1)

作者:jshao https://segmentfault.com/a/1190000012923589 如今市面上关于动画的开源库多得数不胜数,有关于CSS、...

2108
来自专栏葬爱家族

Android高级动画(3)

上一篇文章我们讲了Android中的矢量动画,虽然文中展示的Demo并不多,但是相信大家还是体会到了矢量动画的强大。这里再做一个温故总结:

1521
来自专栏逍遥剑客的游戏开发

Introduction to RenderMonkey

28510
来自专栏Flutter&Dart

Flutter之WidgetsApp使用详解&与MaterialApp的纠缠

如果对MaterialApp不熟悉,可先看我上一篇文章: Flutter之MaterialApp使用详解

4323
来自专栏小灰灰

zxing二维码生成服务之深度定制

二维码生成服务之深度定制 之前写了一篇二维码服务定制的博文,现在则在之前的基础上,再进一步,花样的实现深度定制的需求,我们的目标是二维码上的一切都是可以由用户...

4896
来自专栏性能与架构

将 Redis 作为图数据库

1. 简介 Redis 在 4.0 中正式支持了Module模块系统,使其可以进行丰富的扩展 图数据库的应用越来越广泛,RedisGraph 就是一个 Redi...

4406
来自专栏hightopo

原 荐 快速开发 HTML5 WebGL 的

8623
来自专栏全沾开发(huā)

项目结构——JavaScript版本的2048实现[0]

项目结构——JavaScript版本的2048实现[0] 最近在看一本书《HTML5 Canvas开发详解》 看到了一定程度,打算找...

3816

扫码关注云+社区

领取腾讯云代金券