KshZh / blog

my blog

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Vue 的响应式系统

KshZh opened this issue · comments

commented

Vue 的响应式系统本质上是发布订阅模式,订阅者订阅发布者,发布者产生新消息时通过调用订阅者注册的回调通知订阅者。

在 Vue 中,订阅者主要是组件的渲染函数,渲染函数往往会依赖组件实例的 prop、state、计算属性等发布者,需要这些发布者在其值改变时,通知渲染函数根据最新的状态重新执行产出 VNode 树,diff 旧的 VNode 树,patch 更新对应的 DOM 子树,从而实现组件状态到视图的同步和映射。

Vue 进一步通过 defineProperty、Proxy API 劫持订阅者对响应式数据(发布者)的读写,自动将订阅者注册到访问的响应式数据上,并在响应式数据本身的值变化时,通知到对应的订阅者。这使得框架的使用者更加便利,不必自己检查每个订阅者订阅了哪些响应式数据,手动将订阅者一一注册到订阅的响应式数据上,也不必在响应式数据变化后,手动通知订阅者。

当然,并不是随便一个访问了响应式数据的函数都自动成为该响应式数据的订阅者。在 Vue 中,一个函数想要订阅一个响应式数据的变更,那么需要将该函数创建为一个 Watcher(Vue2) 或 ReactiveEffect(Vue3)。

通知到订阅者后,默认是异步执行订阅者的,因为浏览器重新渲染发生在当次宏任务+微任务之后,线程栈中的代码修改渲染函数订阅的数据 100 次,同步执行 100 次渲染函数和异步执行 1 次渲染函数的效果是一样的,明显后者的性能更好,可以避免频繁生成 VNode,diff VNode,patch DOM。