手写 Vue3 响应式系统:核心就一个数据结构

响应式是 Vue 的特色,如果你简历里写了 Vue 项目,那基本都会问响应式实现原理。

而且不只是 Vue,状态管理库 Mobx 也是基于响应式实现的。

那响应式是具体怎么实现的呢?

与其空谈原理,不如让我们来手写一个简易版吧。

响应式

首先,什么是响应式呢?

响应式就是被观察的数据变化的时候做一系列联动处理。

就像一个社会热点事件,当它有消息更新的时候,各方媒体都会跟进做相关报道。

这里社会热点事件就是被观察的目标。

那在前端框架里,这个被观察的目标是什么呢?

很明显,是状态。

状态一般是多个,会通过对象的方式来组织。所以,我们观察状态对象的每个 key 的变化,联动做一系列处理就可以了。

我们要维护这样的数据结构:

手写 Vue3 响应式系统:核心就一个数据结构插图亿华云

状态对象的每个 key 都有关联的一系列 effect 副作用函数,也就是变化的时候联动执行的逻辑,通过 Set 来组织。

每个 key 都是这样关联了一系列 effect 函数,那多个 key 就可以放到一个 Map 里维护。

这个 Map 是在对象存在的时候它就存在,对象销毁的时候它也要跟着销毁。(因为对象都没了自然也不需要维护每个 key 关联的 effect 了)

而 WeakMap 正好就有这样的特性,WeakMap 的 key 必须是一个对象,value 可以是任意数据,key 的对象销毁的时候,value 也会销毁。

所以,响应式的 Map 会用 WeakMap 来保存,key 为原对象。

这个数据结构就是响应式的核心数据结构了。

比如这样的状态对象:

const obj = {

a: 1,

b: 2

}

它的响应式数据结构就是这样的:

const depsMap = new Map();

const aDeps = new Set();

depsMap.set(a, aDeps);

const bDeps = new Set();

depsMap.set(b, bDeps);

const reactiveMap = new WeakMap()

reactiveMap.set(obj, depsMap);

创建出的数据结构就是图中的那个:

手写 Vue3 响应式系统:核心就一个数据结构插图1亿华云

手写 Vue3 响应式系统:核心就一个数据结构插图2亿华云

然后添加 deps 依赖,比如一个函数依赖了 a,那就要添加到 a 的 deps 集合里:

effect(() =

THE END
Copyright © 2024 亿华云