Pelaksanaan
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(); });
sebenarnya hampir sama dengan pelaksanaan reactive
kami sebelum ini, satu-satunya perbezaan ialah apabila set
pencetus tidak dicetuskan, tetapi amaran. Sudah tentu, kerana ia tidak akan diubah, track
tidak diperlukan.
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; }, }); }
Seperti yang anda lihat, pelaksanaan readonly
dan reactive
sebenarnya sangat serupa, jadi kami boleh memfaktorkannya semula untuk meningkatkan kebolehskalaan seterusnya.
Apa yang saya katakan adalah serupa, ia merujuk kepada beberapa perangkap (penangkap) dalam pengendali (objek pemproses) dalam new Proxy(target, handlers)
. Iaitu, get
, set
kaedah ini.
Kami boleh mencipta fungsi perangkap tersebut melalui fungsi kilang untuk memudahkan kod kami dan meningkatkan kebolehselenggaraan.
Selain itu, kita mengandaikan perangkap boleh dihasilkan oleh kilang, iaitu bahagian pengendali adalah bersamaan dengan yang ditentukan, new Proxy
Bahagian ini juga perlu dibuat melalui fungsi kilang.
Kami mula-mula mengekstrak fail awam 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; };
dan kemudian 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); }
Atas ialah kandungan terperinci Apakah kaedah untuk melaksanakan baca sahaja secara responsif dalam vue3. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!