实现vue3响应式系统核心-shallowReactive
- 创业
- 2025-08-05 00:36:02

简介
今天来实现一下 shallowReactive 这个 API。
reactive函数是一个深响应,当你取出的值为对象类型,需要再次调用 reactive进行响应式处理。很明显我们目前的代码是一个浅响应,即 只代理了对象的第一层,也就是 shallowReactive。
代码地址: https://github.com/SuYxh/share-vue3
代码并没有按照源码的方式去进行组织,目的是学习、实现 vue3 响应式系统的核心,用最少的代码去实现最核心的能力,减少我们的学习负担,并且所有的流程都会有配套的图片,图文 + 代码,让我们学习更加轻松、快乐。
每一个功能都会提交一个 commit ,大家可以切换查看,也顺变练习练习 git 的使用。
单元测试 it('深响应 reactive', () => { const mockFn = vi.fn(); const obj = reactive({ foo: { bar: 1 } }) effect(function effectFn() { console.log(obj.foo.bar); }) expect(mockFn).toHaveBeenCalledTimes(1); obj.foo.bar = 2 expect(mockFn).toHaveBeenCalledTimes(2); }) it('浅响应 shallowReactive', () => { const mockFn = vi.fn(); const obj = shallowReactive({ foo: { bar: 1 } }) effect(function effectFn() { console.log(obj.foo.bar); }) expect(mockFn).toHaveBeenCalledTimes(1); obj.foo.bar = 2 expect(mockFn).toHaveBeenCalledTimes(1); }) 代码实现在 reactive函数的get中,增加如下判断:
if (typeof res === 'object' && res !== null) { return reactive(res) }新增一个shallowReactive 函数并导出, 和之前的 reactive函数一样。
运行单测深响应 reactive:
浅响应 shallowReactive:
都没有问题!
重构我们看到 shallowReactive 和 reactive有极大的相似,需进行代码抽离:
export function createReactive(target, isShallow = false) { return new Proxy(target, { // 拦截读取操作 get(target, key, receiver) { // 代理对象可以通过 raw 属性访问原始数据 if (key === symbolRaw) { return target; } const res = Reflect.get(target, key, receiver); // 如果是浅响应,则直接返回原始值 if (isShallow) { return res; } if (typeof res === "object" && res !== null) { return reactive(res); } // 依赖收集 track(target, key); return res; }, // 拦截设置操作 set(target, key, newVal, receiver) { // 先获取旧值 const oldVal = target[key]; // 如果属性不存在,则说明是在添加新属性,否则是设置已有属性 const type = Object.prototype.hasOwnProperty.call(target, key) ? TriggerType.SET : TriggerType.ADD; // 设置属性值 const res = Reflect.set(target, key, newVal, receiver); // target === receiver.raw 说明 receiver 就是 target 的代理对象 if (target === receiver[symbolRaw]) { // 较新值与旧值,只有当它们不全等,并且不都是 NaN 的时候才触发响应 if (oldVal !== newVal && (oldVal === oldVal || newVal === newVal)) { trigger(target, key, type); } } return res; }, // 拦截 in 操作符 has(target, key) { track(target, key); return Reflect.has(target, key); }, // 拦截 for in 循环 ownKeys(target) { track(target, ITERATE_KEY); return Reflect.ownKeys(target); }, // 拦截删除 deleteProperty(target, key) { // 检查被操作的属性是否是对象自己的属性 const hadKey = Object.prototype.hasOwnProperty.call(target, key); // 使用 Reflect.deleteProperty 完成属性的删除 const res = Reflect.deleteProperty(target, key); if (res && hadKey) { // 只有当被删除的属性是对象自己的属性并且成功删除时,才触发更新 trigger(target, key, TriggerType.DEL); } return res; }, }); } // 对原始数据的代理 export function reactive(target) { return createReactive(target); } export function shallowReactive(target) { return createReactive(target, true); } 运行测试 pnpm test重构后的代码也没有问题!
一个前端小学生的学习之路,如果你喜欢前端,我们可以一起进行学习、交流、共建。可以添加好友,结伴学习,成长的路上不孤单!
实现vue3响应式系统核心-shallowReactive由讯客互联创业栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“实现vue3响应式系统核心-shallowReactive”
下一篇
【30秒看懂大数据】变量