reactive readonly嵌套对象转换功能实现详解

这篇文章主要为大家介绍了reactive readonly嵌套对象转换功能实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助!

一、单元测试

reactive

// src/reactivity/tests/reactive.spec.ts
it('nested reactive', () => {
  const original = {
nested: { foo: 1 },
array: [{ bar: 2 }]
  };
  const observed = reactive(original);
  expect(isReactive(observed.nested)).toBe(true);
  expect(isReactive(observed.array)).toBe(true);
  expect(isReactive(observed.array[0])).toBe(true);
});

readonly

it('nested readonly', () => {
  const original = { foo: 1, bar: { baz: 2 } };
  const wrapped = readonly(original);
  expect(isReadonly(wrapped)).toBe(true);
  expect(isReadonly(wrapped.bar)).toBe(true);
});

二、代码实现

为什么嵌套的深层对象没有转换成reactivereadonly呢?

因为Proxy劫持的是对象本身,并不能劫持子对象的变化。

其实通过单测可以看出,我们只需要将reactive嵌套的里层对象也转换成reactive,将readonly嵌套的里层对象也转换成readonly

那只需要在get中,返回res的时候,将res转换成相应的代理就可以了。

function createGetter(isReadonly = false) {
  return function get(target, key) {
const res = Reflect.get(target, key);
if (key === ReactiveFlags.IS_REACTIVE) {
  return !isReadonly;
} else if (key === ReactiveFlags.IS_READONLY) {
  return isReadonly;
}
if (isObject(res)) {
  return isReadonly ? readonly(res) : reactive(res);
}
if (!isReadonly) {
  track(target, key);
}
return res;
  };
}

跑一下完整的单测结果看下:

ps: 其实这里需要注意的一点就是,在get中处理嵌套转换,我们只有在用到这个子对象的时候,才会将这个子对象 转换成响应时代理,避免了不必要的性能浪费。对比vue2的递归遍历defineProperty来说,也是一个优化的地方。

webpack5之devServer的常用配置详解 网站建设

webpack5之devServer的常用配置详解

devServer是为开发过程中, 开启的一个本地服务,在此总结一些常用的配置。供大家学习,相互成长,相互进步! 一. contentBase devServer中contentBase对于我们直...
深入理解JavaScript中实例对象和new命令 网站建设

深入理解JavaScript中实例对象和new命令

面向对象编程(Object Oriented Programming,缩写为OOP)是目前主流的编程范式。它将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟...
vue项目网站全局置灰功能实现示例详解 网站建设

vue项目网站全局置灰功能实现示例详解

这篇文章主要为大家介绍了vue项目网站全局置灰功能实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助! 1、前端独立实现 两种不同的逻辑,一种是前端自己实现,一种是结合后台管理系统...