Vue双向绑定

写在前面

Vue.js 最核心的功能有两个,一是响应式的数据绑定系统,二是组件系统。我所理解的双向数据绑定就是当数据变化时视图自动更新,当视图变化时数据自动更新。

实现数据绑定的做法有大致如下几种:

  • 发布者-订阅者模式(backbone.js)
  • 脏值检查(angular.js)
  • 数据劫持(vue.js)

发布者-订阅者

一般通过sub, pub的方式实现数据和视图的绑定监听,更新数据方式通常做法是 vm.set(‘property’, value)。

脏值检查

angular.js 是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图,最简单的方式就是通过 setInterval() 定时轮询检测数据变动,当然Google不会这么low,angular只有在指定的事件触发时进入脏值检测。

数据劫持

vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

Vue双向绑定

当视图变化时数据自动更新时比较简单,可以通过监听视图的change事件,当视图变化直接调用更新函数更新数据。

当数据变化时视图自动更新是双向绑定的重点。

让我们先来看一下官网的这张数据绑定的说明图:

官网双向绑定说明图

原理图告诉我们,Data中的属性定义了getter、setter对属性进行劫持,当属性值改变是就会notify通知watcher对象,而watcher对象则会notify到view上对应的组件进行更新,然后我们就看到了视图的更新了,反过来当在视图输入数据时,也会触发订阅者watcher,更新最新的数据到data里面,这样model数据就能实时响应view上的数据变化了,这样一个过程就是数据的双向绑定了。

原理分析

通过上面的介绍我们发现整个过程需要需要几个对象:

  • 订阅器Dep:实现新增订阅者、通知订阅者的功能
  • 监听器Observer:通过Object.defineProperty()定义属性的getter、setter。
  • 订阅者Watcher:实现view视图指令及数据和model层数据联系的管道,当在执行编译时候,他会把对应的属性创建一个Watcher对象让他和数据层model建立起联系。但数据发生变化是会触发update方法更新到视图上view中,反过来亦然。
  • 编译器Compile:负责解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。