npuer 发表于 2022-10-19 22:32:20

深入响应性原理

Vue 最独特的特性之一,是其非侵入性的响应性系统。
Proxy 对象
Vue 在内部跟踪所有已被设置为响应式的对象,因此它始终会返回同一个对象的 Proxy 版本。

从响应式 Proxy 访问嵌套对象时,该对象在返回之前也被转换为 Proxy:

const handler = {
get(target, prop, receiver) {
    track(target, prop)
    const value = Reflect.get(...arguments)
    if (isObject(value)) {
      return reactive(value)
    } else {
      return value
    }
}
// ...
}
Proxy vs 原始标识
Proxy 的使用确实引入了一个需要注意的新警告:在身份比较方面,被代理对象与原始对象不相等 (===)。例如:

const obj = {}
const wrapped = new Proxy(obj, handlers)
console.log(obj === wrapped) // false
在大多数情况下,原始版本和包装版本的行为相同,但请注意,它们在依赖严格比对的操作下将是失败的,例如 .filter() 或 .map()。使用选项 API 时,这种警告不太可能出现,因为所有响应式都是从 this 访问的,并保证已经是 Proxy。

但是,当使用合成 API 显式创建响应式对象时,最佳做法是不要保留对原始对象的引用,而只使用响应式版本:

const obj = reactive({
count: 0
}) // no reference to original
侦听器
每个组件实例都有一个相应的侦听器实例,该实例将在组件渲染期间把“触碰”的所有 property 记录为依赖项。之后,当触发依赖项的 setter 时,它会通知侦听器,从而使得组件重新渲染。

将对象作为数据传递给组件实例时,Vue 会将其转换为 Proxy。这个 Proxy 使 Vue 能够在 property 被访问或修改时执行依赖项跟踪和更改通知。每个 property 都被视为一个依赖项。

首次渲染后,组件将跟踪一组依赖列表——即在渲染过程中被访问的 property。反过来,组件就成为了其每个 property 的订阅者。当 Proxy 拦截到 set 操作时,该 property 将通知其所有订阅的组件重新渲染。
页: [1]
查看完整版本: 深入响应性原理