vue3响应式 - 实现readonly
前言
前面的章节我们把 effect
部分大致讲完了,这部分我们来讲 readonly
以及重构一下reactive
。
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
的时候不要触发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;
},
});
}
重构
可以看到,readonly
和 reactive
实现其实很类似,那我们可以重构一下,增强后续的拓展性。
至于我说的类似,指的是 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);
}
PS
本篇幅比较短小,但是算是为后续打下了一些基础吧。因为笔者发现边学边写总结文章速度很慢,然后写完 effect
那几篇之后就开始直接一路往下学,中途虽然有提交git,但是没有打tag的习惯,搞的现在回来来写文章有点无从下手。
不过最近应该快把diff那部分搞定了,到时候应该会加快速度更新。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanfekkf
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01