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

Heim  >  Artikel  >  Web-Frontend  >  Was ist die Methode, um in vue3 schreibgeschützt und reaktionsfähig zu implementieren?

Was ist die Methode, um in vue3 schreibgeschützt und reaktionsfähig zu implementieren?

WBOY
WBOYnach vorne
2023-05-20 22:19:221481Durchsuche

Die Implementierung von

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

ist unserer vorherigen Implementierung von reactive tatsächlich sehr ähnlich. Der Unterschied besteht darin, dass der Trigger nicht ausgelöst wird, wenn set verwendet wird, sondern eine Warnung . Da es natürlich nicht geändert wird, ist track nicht erforderlich. 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.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);
}

Refactoring🎜🎜Sie sehen, dass die Implementierungen von readonly und reactive tatsächlich sehr ähnlich sind, sodass wir sie umgestalten können, um die spätere Skalierbarkeit zu verbessern. 🎜🎜Was ich gesagt habe, ist ähnlich, es bezieht sich auf einige Traps (Capturer) in den Handlern (Prozessorobjekten) in new Proxy(target, handlers). Das heißt, get, set dieser Methoden. 🎜🎜Wir können diese Traps-Funktionen über Factory-Funktionen erstellen, um unseren Code zu vereinfachen und die Wartbarkeit zu verbessern. 🎜🎜Darüber hinaus gehen wir davon aus, dass Traps von Fabriken erzeugt werden können, das heißt, der Handler-Teil entspricht der Bestimmung, und der neue Proxy-Teil sollte ebenfalls über die Fabrikfunktion erstellt werden. 🎜🎜Wir extrahieren zuerst eine öffentliche Datei baseHandler.ts🎜rrreee🎜und dann unsere reactive.ts🎜rrreee

Das obige ist der detaillierte Inhalt vonWas ist die Methode, um in vue3 schreibgeschützt und reaktionsfähig zu implementieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen