您的位置:首页 > 技术中心 > 前端框架 >

vue3响应式实现readonly的方法是什么

时间:2023-05-21 07:24

readonly的实现

it("happy path", () => {    console.warn = vi.fn();    const original = {      foo: 1,    };    const observed = readonly({      foo: 1,    });    expect(original).not.toBe(observed);    expect(observed.foo).toBe(1);    //  set不起作用    observed.foo = 2;     expect(observed.foo).toBe(1);    //  当被set的时候,发出一个警告    expect(console.warn).toBeCalled();  });

其实与我们之前实现 reactive 十分的类似,区别只不过是set 的时候不要触发trigger,而是警告。当然既然是不会被改变的,track 也是不必要的。

export function readonly(raw) {     return new Proxy(raw, {         get(target, key) {             const res = Reflect.get(target, key);             return res;         },         set(target, key, newValue, receiver) {            console.warn(              `property: ${String(key)} can't be set, beacase ${target} is readonly.`            );            return true;      },    }); }export function reactive(raw) {     return new Proxy(raw, {         get(target, key) {             const res = Reflect.get(target, key);             // 依赖收集             track(target, key);             return res;         },         set(target, key, value) {             const res = Reflect.set(target, key, value);             // 触发依赖             trigger(target, key);             return res;         },     }); }

重构

可以看到,readonlyreactive 实现其实很类似,那我们可以重构一下,增强后续的拓展性。

至于我说的类似,指的是 new Proxy(target, handlers) 中的handlers(处理器对象)中的一些traps(捕获器)。即get, set 这些方法。

我们可以通过工厂函数来创建那些traps函数,来简化我们的代码,提高可维护性。

另外,我们假定traps可以有工厂可以生产了,即handlers这部分相当于被定下来了,new Proxy 这部分也理应可以通过工厂函数创造出来。

我们先抽出一个公共的文件 baseHandler.ts

//  baseHanlder.tsimport { track, trigger } from "./effect";//  get的工厂函数function createGetter(isReadonly = false) {  return function get(target, key) {    const res = Reflect.get(target, key);    if (!isReadonly) {      track(target, key);    }    return res;  };}function createSetter() {  return function set(target, key, newValue, receiver) {    const res = Reflect.set(target, key, newValue, receiver);    trigger(target, key, type, newValue);    return res;  };}export const mutableHandler = {  get: createGetter(),  set: createSetter(),};export const readonlyHandler = {  get: createGetter(),  set(target, key, newValue, receiver) {    console.warn(      `property: ${String(key)} can't be set, beacase ${target} is readonly.`    );    return true;};

然后是我们的reactive.ts

//  reactive.tsimport {  mutableHandler,  readonlyHandler,} from "./baseHandlers";//  proxy的工厂函数function createReactiveObject(  target,  baseHandlers: ProxyHandler<any>) {  return new Proxy(target, baseHandlers);}export function reactive(target) {  return createReactiveObject(target, mutableHandler);}export function readonly(target) {  return createReactiveObject(target, readonlyHandler);}

以上就是vue3响应式实现readonly的方法是什么的详细内容,更多请关注Gxl网其它相关文章!

热门排行

今日推荐

热门手游