vue3 响应式
回顾 Object.defineProperty
基本用法
js
// Object.defineProperty 的基本用法
const data = {}
const name = 'zhangsan'
Object.defineProperty(data, "name", {
get: function () {
console.log('get')
return name
},
set: function (newVal) {
console.log('set')
name = newVal
}
});
// 测试
console.log(data.name) // 可以监听到
data.name = 'lisi' // 可以监听到监听数据变化,参考 code-1.js
总结 Object.defineProperty 缺点:
- 深度监听,需要递归到底
- 无法监听新增属性/删除属性(Vue.set Vue.delete)
- 无法监听数组,需要特殊处理
使用 Proxy
我们已知:
- Proxy 可以原生监听 新增/删除属性
- Proxy 原生支持监听数组变化
接下来看看 Proxy 如何实现深度监听。参考 code-2.js
两者对比
- 深度监听,都用递归。但前者是一次性递归,后者是访问时再递归。
- Proxy 原生能监听 新增/删除属性
- Proxy 原生支持监听数组变化
但 —— Proxy 兼容性不好 ,我见过,oppo vivo 的某些机型,某些 app 的 webview 还没有支持 ES6 。
vue3 响应式实现
响应式的作用:监听 data 数据变化,仅此而已。所以,不要掺杂进其他功能进来。
回顾
- 回顾 Object.defineProperty 方式
- 回归 Proxy 语法
- 回顾 Map 和 Set 语法
Proxy 实现
用 Proxy 模仿 Vue 3.0 的响应式
学习用法
- 下载 vue-next ,然后查看测试用例,看
packages/reactivity/__tests__/effect.spec.ts - 找
basic properties,找到使用方式
源码编写,步骤如下
reactivity-1.js实现简单的 Proxy 监听reactivity-2.js深度监听,修改get的代码reactivity-3.js监听数组,修改get去掉原型方法,修改set区分新增属性和修改属性,不重复修改属性reactivity-4.js避免重复代理- 新建
toProxyMap和toRawMap createReactiveObject中- 创建 proxy 之前,判断
toProxyMap是否有对应的 proxy - 创建 Proxy 之前,判断
toRawMap是否已有对应的 proxy - 生成 proxy 之后,设置
toProxyMap - 生成 proxy 之后,设置
toRawMap
- 创建 proxy 之前,判断
- 新建
reactivity-5.js接收副作用,先初始化时能执行一次。创建effectcreateReactiveEffectrun和activeEffectStacksreactivity-6.js响应式副作用- 新建
targetsMap - 新建
track函数,并在get时执行 - 新建
trigger函数,并在set时执行
- 新建
总结 Proxy 比 Object.defineProperty 的优点?
- 深度监听时,Proxy 延迟递归,而不是一上来就全部递归,性能好
- 原生支持监听数组
- 原生支持新增和删除属性

讨论区
欢迎留下想法与补充