{console.warn=vi.fn();constoriginal={foo:1,};constobserved=readonly({foo:1,});expect(original) .not.toBe(observed);expect(observed.foo).toBe(1);//set ne fonctionne pas observé.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 ne fonctionne pas observé.foo=2;expect(observed.foo).toBe(1);//when set ,">

Maison  >  Article  >  interface Web  >  Quelle est la méthode pour implémenter la lecture seule de manière réactive dans vue3

Quelle est la méthode pour implémenter la lecture seule de manière réactive dans vue3

WBOY
WBOYavant
2023-05-20 22:19:221480parcourir

readonly Implementation

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

En fait, c'est très similaire à notre précédente implémentation de reactive. La seule différence est que le déclencheur ne doit pas être déclenché lorsque set , mais un avertissement. Bien entendu, puisqu'il ne sera pas modifié, <code>track n'est pas nécessaire. 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&#39;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&#39;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#🎜🎜##🎜🎜#Comme vous pouvez le voir, les implémentations readonly et reactive sont en fait très similaires, nous pouvons donc refactoriser pour améliorer l’évolutivité ultérieure. #🎜🎜##🎜🎜#Quant à ce que j'ai dit est similaire, cela fait référence à certains pièges (capteurs) dans les gestionnaires (objets processeur) dans nouveau proxy (cible, gestionnaires). Autrement dit, get, set ces méthodes. #🎜🎜##🎜🎜#Nous pouvons créer ces fonctions de pièges via des fonctions d'usine pour simplifier notre code et améliorer la maintenabilité. #🎜🎜##🎜🎜# De plus, nous supposons que les pièges peuvent être produits par les usines, c'est-à-dire que la partie gestionnaires équivaut à être déterminée, et la partie nouveau proxy doit également être créée via la fonction d'usine. #🎜🎜##🎜🎜#Nous extrayons d'abord un fichier public baseHandler.ts#🎜🎜#rrreee#🎜🎜#Puis notre reactive.ts#🎜 🎜 #rrreee

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer