Vue.js 中的双向数据绑定是如何实现的?

在 Vue.js 中,双向数据绑定是通过数据劫持与发布者-订阅者模式实现的。
实现双向数据绑定的步骤:

  1. 使用 Object.defineProperty() 将对象的属性转换为 getter/setter。
js
function defineReactive(data, key, val) {
  Object.defineProperty(data, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      return val
    },
    set: function reactiveSetter(newVal) {
      val = newVal
    }
  })
}
  1. 在 getter 中收集依赖,在 setter 中触发依赖更新。
js
let dep = []    // 依赖集合

function defineReactive(data, key, val) {
  let dep = new Dep()

  Object.defineProperty(data, key, {
    get: function reactiveGetter() {
      // 收集依赖
      dep.depend()    
      return val
    },
    set: function reactiveSetter(newVal) { 
      if (val === newVal) return
      val = newVal
      // 触发依赖更新
      dep.notify()     
    }
  })  
}
  1. 模板编译时将解析出的依赖推送给相应的 dep。
js
function compile(node) {
  // 解析模板,获取依赖 key 
  let key = parse(node.textContent)  

  node.textContent = val[key]

  // 收集依赖
  dep.depend()  
}
  1. 当数据改变触发 setter 时,dep 将通知所有依赖更新视图。

以上就是 Vue.js 双向数据绑定的实现原理。通过 getter/setter 收集依赖与触发更新,配合发布者-订阅者模式, elegant 地实现了数据与视图的绑定。