vue响应式(双响绑定)原理

@一棵菜菜  April 23, 2018

Vue简介

Vue.js 不是一个框架,它只是一个提供 MVVM 风格的双向数据绑定的库,专注于 UI 层面。Vue.js 可以说是MVVM 架构的最佳实
践,专注于 MVVM 中的 ViewModel,不仅做到了数据双向绑定,而且也是一款相对比较轻量级的JS 库,API 简洁,很容易上手。

QQ20180423-234413.png

快速理解

Vue.js 提供的核心是 MVVM 中的 VM,也就是 ViewModel。ViewModel 负责连接 View 和 Model,保证视图和数据的一致性。在组件化这一点上,Vue.js可以定义可复用和嵌套的组件类,并且可以在模板中声明式地使用组件。

Vue.js 的最大特点就是上手简单:你不需要理解 Angular 的依赖注入是什么东东、$digest 和 $apply, preLink 和 postLink 有什么区别... 在 Vue.js 的定义中,View 就是用户实际看到的 DOM 元素,而 Model 就是原生的JavaScript 对象。作为开发者,真正需要关注的只有 ViewModel,也就是 Vue.js 所提供的 Vue 构建函数:

var vm = new Vue({
    // 选项...
})

那么 ViewModel 是如何连接 View 和 Model 的呢?假设我们有这样的 HTML:

<div id="demo">
    <p>{{message}}</p>
    <input v-model="message">
</div>

然后有这样的数据:

var data = {
    message: 'Hello Vue.js!'
}

我们要做的就是这样:

var demo = new Vue({
    el: '#demo',
    data: data
})

效果:http://jsfiddle.net/yyx990803/vjvMp/

看上去就像是渲染了个模板而已,但其实 Vue.js 已经建立了 DOM 和数据之间的连接,此时任何对 data.message 的改动,都会触发 DOM 的更新。而更神奇的是 v-model 这条 directive 是双向的数据绑定,当用户在输入栏里打字的时候,数据会被同步回 data.message 当中去。

另外方便的是,返回的 demo 这个 ViewModel 对象会自动代理 data 上的属性,所以你可以直接运行 demo.message = 'what!',能够得到和直接操作数据一样的结果。这个特点在之后会常常用到。

除了直接绑定一个数据值之外,你还可以在绑定中使用表达式:

<div id="demo">
    <p>{{message.split('').reverse().join('')}}</p>
    <input v-model="message">
</div>

效果:http://jsfiddle.net/yyx990803/vjvMp/1/ 你在输入框中输入的文字会被实时倒转。

原文见http://www.html-js.com/article/Vuejs-Chinese-entry-1-super-simple-MVVM.

深入理解Vue的双向绑定

Vue.js 是采用 Object.defineProperty (不明白的请自学js这部分)的 getter 和 setter,并结合观察者模式来实现数据绑定的。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

849589-20161106211631549-2019592745.png

Observer 数据监听器,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者,内部采用Object.defineProperty的getter和setter来实现。

Compile 指令解析器,它的作用对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数。

Watcher 订阅者, 作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数。

Dep 消息订阅器,内部维护了一个数组,用来收集订阅者(Watcher),数据变动触发notify 函数,再调用订阅者的 update 方法。

从图中可以看出,当执行 new Vue() 时,Vue 就进入了初始化阶段,一方面Vue 会遍历 data 选项中的属性,并用 Object.defineProperty 将它们转为 getter/setter,实现数据变化监听功能;另一方面,Vue 的指令编译器Compile 对元素节点的指令进行扫描和解析,初始化视图,并订阅Watcher 来更新视图, 此时Wather 会将自己添加到消息订阅器中(Dep),初始化完毕。

当数据发生变化时,Observer 中的 setter 方法被触发,setter 会立即调用Dep.notify(),Dep 开始遍历所有的订阅者,并调用订阅者的 update 方法,订阅者收到通知后对视图进行相应的更新。

推荐看这篇文章就够了:《剖析Vue原理&实现双向绑定MVVM》
推荐结合看源码就够了:vue双向绑定官方源码

《Vue.js 和 MVVM 小细节》
vue 官方文档


添加新评论