{console.warn=vi.fn();constoriginal={foo:1,};constobserved=readonly({foo:1,});expect(original) . not.toBe(observed);expect(observed.foo).toBe(1);//set は機能しません Observed.foo=2;expect(observed.foo).toBe(1);//set の場合、"/> {console.warn=vi.fn();constoriginal={foo:1,};constobserved=readonly({foo:1,});expect(original) . not.toBe(observed);expect(observed.foo).toBe(1);//set は機能しません Observed.foo=2;expect(observed.foo).toBe(1);//set の場合、">

ホームページ  >  記事  >  ウェブフロントエンド  >  vue3でreadonlyをレスポンシブに実装する方法は何ですか

vue3でreadonlyをレスポンシブに実装する方法は何ですか

WBOY
WBOY転載
2023-05-20 22:19:221481ブラウズ

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 のときにトリガーがトリガーされないことですが、警告。もちろん変更しないので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) のハンドラー (プロセッサ オブジェクト) 内のいくつかのトラップ (キャプチャラー) を指します。つまり、getset これらのメソッドです。

ファクトリ関数を通じてこれらのトラップ関数を作成し、コードを簡素化し、保守性を向上させることができます。

さらに、トラップはファクトリによって生成できる、つまりハンドラー部分が決定されることに等しいと仮定します。

new Proxy この部分もファクトリ関数を通じて作成する必要があります。

最初にパブリック ファイル

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

を抽出し、次に

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);
}
を抽出します。

以上がvue3でreadonlyをレスポンシブに実装する方法は何ですかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。