返回

Vue.js 响应式系统内核剖析:Observe 机制揭秘

前端

在上一篇文章中,我们深入探究了 Vue.js 的声明、初始化和初始化状态机制。本篇将继续深入 Vue.js 的核心,揭开 Observe 机制的奥秘。Observe 是 Vue.js 响应式系统的重要组成部分,它负责侦听数据的变化并通知受影响的组件。

Observe 主要由两个部分组成:Dep(依赖项)和 Watcher(观察者)。我们从 Observe 的入口文件 src/core/observe/index.js 开始。

1. Dep:依赖项

Dep 用于收集和管理对数据项的依赖关系。它通过一个 subs 数组存储这些依赖项。当数据项发生变化时,Dep 负责通知所有已订阅的依赖项。

export class Dep {
  constructor() {
    this.subs = []
  }

  addSub(sub) {
    this.subs.push(sub)
  }

  notify() {
    this.subs.forEach(sub => sub.update())
  }
}

2. Watcher:观察者

Watcher 负责观察数据项的变化并执行相应的回调函数。它包含一个 vm(Vue 实例)、getter(用于获取数据项)和 callback(在数据项发生变化时执行的函数)。

export class Watcher {
  constructor(vm, expOrFn, cb) {
    this.vm = vm
    this.getter = expOrFn
    this.callback = cb
  }

  update() {
    this.run()
  }

  run() {
    let value = this.get()
    let oldVal = this.value
    this.value = value
    this.callback.call(this.vm, value, oldVal)
  }

  get() {
    return this.getter.call(this.vm, this.vm)
  }
}

3. Observe 入口

src/core/observe/index.js 中,提供了 Observe 入口函数 observe。该函数根据传入数据的类型(对象、数组或响应式对象)进行不同的处理。

对于对象,它会遍历其所有属性并将其转换为响应式属性。对于数组,它会将数组包装为响应式数组。对于响应式对象,它会直接返回该对象。

export function observe(value) {
  if (!isObject(value)) return value

  let ob = new Observer(value)
  if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
    return value.__ob__
  } else {
    return ob
  }
}

4. Observer:响应式对象

Observer 类是 Observe 的核心,负责将普通对象转换为响应式对象。它拥有一个 value(原始数据)和一个 dep(依赖项集合)。

当 Observer 被创建时,它会遍历 value 中的所有属性并将其转换为响应式属性。对于每个属性,它都会创建并添加一个 Dep 实例到属性上。

export class Observer {
  constructor(value) {
    this.value = value
    this.dep = new Dep()
    this.walk(value)
  }

  walk(obj) {
    for (let key in obj) {
      defineReactive(obj, key, obj[key])
    }
  }
}

5. defineReactive:定义响应式属性

defineReactive 函数负责将普通属性转换为响应式属性。它会创建一个 Dep 实例并将其与属性关联。当属性发生变化时,Dep 会通知所有订阅它的依赖项。

export function defineReactive(obj, key, val) {
  const dep = new Dep()
  Object.defineProperty(obj, key, {
    configurable: true,
    enumerable: true,
    get: function reactiveGetter() {
      dep.depend()
      return val
    },
    set: function reactiveSetter(newVal) {
      const value = val
      val = newVal
      dep.notify()
    },
  })
}

总结

Vue.js 的 Observe 机制是一个复杂而精妙的系统。它通过 Dep 和 Watcher 的协作,实现了数据变化的侦听和响应。通过对源码的深入分析,我们可以更好地理解 Vue.js 响应式系统的强大功能。