Vue 在初始化数据时,会对 data 进行遍历,并使用 Object.defineProperty 把这些属性转为 getter/setter。 每个组件实例都对应一个 watcher 实例,当页面使用对应属性 时,首先会用 getter 进行依赖收集(收集当前组件的 watcher) 如果属性发生变化 setter 触发时会通知相关依赖进行更新操作(发布订阅)。
注意:
1. Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
2. 由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。
vue 的双向数据绑定实现的底层原理
我们所说的数据双向绑定,一定是对于 UI 控件来说的,非 UI 控件不会涉及到双向绑定
Vue 是用数据劫持和发布订阅模式来实现双向数据绑定的,其中数据劫持是利用了 object.defineProprety 这个方法。他给数据对象中的每个属性添加了 set 和 get 的方法。所以在数据写入和读取的时候,都可以触发对应的自定义方法。
我们已经知道实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器 Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者 Watcher 看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器 Dep 来专门收集这些订阅者,然后在监听器 Observer 和订阅者 Watcher 之间进行统一管理的。接着,我们还需要有一个指令解析器 Compile,对每个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者 Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者 Watcher 接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。因此接下去我们执行以下 3 个步骤,实现数据的双向绑定:<hr> 1.实现一个监听器 Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。<hr> 2.实现一个订阅者 Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。<hr> 3.实现一个解析器 Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。