{console.warn=vi.fn();constoriginal={foo:1,};constobserved=readonly({foo:1,});expect(original). not.toBe(observed);expect(observed.foo).toBe(1);//set does not work observed.foo=2;expect(observed.foo).toBe(1);//when set ,"/> {console.warn=vi.fn();constoriginal={foo:1,};constobserved=readonly({foo:1,});expect(original). not.toBe(observed);expect(observed.foo).toBe(1);//set does not work observed.foo=2;expect(observed.foo).toBe(1);//when set ,">

Home  >  Article  >  Web Front-end  >  What is the method to implement readonly responsively in vue3

What is the method to implement readonly responsively in vue3

WBOY
WBOYforward
2023-05-20 22:19:221481browse

The implementation of

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();
  });

is actually very similar to our previous implementation of reactive. The difference is that the trigger is not triggered when set, but a warning. Of course, since it will not be changed, track is also unnecessary.

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; 
        }, 
    }); 
}

Refactoring

As you can see, the implementations of readonly and reactive are actually very similar, so we can refactor them to enhance subsequent expansion. sex.

As for what I said is similar, it refers to some traps (capturers) in the handlers (processor objects) in new Proxy(target, handlers). That is, get, set these methods.

We cancreate those traps functions through factory functions to simplify our code and improve maintainability.

In addition, we assume that traps can be produced by factories, that is, the handlers part is equivalent to being determined, new Proxy This part should also be created through the factory function.

We first extract a public file baseHandler.ts

//  baseHanlder.ts
import { 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;
};

and then our reactive.ts

//  reactive.ts
import {
  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);
}

The above is the detailed content of What is the method to implement readonly responsively in vue3. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete