在 TypeScript 中使用代理作为 object.property 观察器



我编写了一个排序映射类型的对象(SortedMap(,它存储了实现此MapItem接口的对象。

export interface MapItem {
id: string;
sort: number;
index: number;
}

我希望 SortedMap 在有人更改其内部存储中其中一个 MapItems 的排序属性时重新调整其集合,因此当我看到排序更改时,我正在尝试触发度假村。 当将新项添加到集合中时,我想添加某种"观察程序",以查找任何集合 MapItem.sort 属性中的更改。

我认为我可以按照 MDN 代理上描述的模式使用代理来做到这一点,所以编写了这个函数,当将新项目添加到 SortedMap 时调用

private addSortChangeHandler(item: MapItem) {
let self = this;
let watcher = {
set(obj: MapItem, prop: string, value: number | string) {
switch (prop) {
case "sort":
if (value <= 0) {
obj.sort = -1
} else {
obj.sort = <number>value;
}
self.sortIndex();
break;
case "index":
obj.index = <number>value;
break;
case "id":
obj.id = <string>value;
break;
}
}
}
let proxy = new Proxy(item, watcher);
this._watcher.push(proxy);
}

但是,编译器有一长串投诉,其值watcher在语句let proxy = new Proxy(item, watcher)中。 不知道如何解决这个问题。 代理的文档在TypeScript文档本身中几乎不存在。

一旦我解决了这个问题,只要对象在排序的 Map 中,我需要将这些 Proxy 对象保存在某个地方(在上面代码this._watchers数组中(是否正确,否则它们将被垃圾回收? 还是它们以某种方式绑定到它们所附着的对象上?

好的,我偶然发现了它。 如果有人希望实现类似的:

private addSortChangeHandler(item: MapItem): MapItem {
let self = this;
let watcher = <ProxyHandler<MapItem>>{}
watcher.set = function (target, p, value, receiver) {
switch (p) {
case "sort":
if (self._sorting) {
target.sort = <number>value;  //a new item is being added
} else {  //the item is already in the colleciton
if (value <= 0) {
target.sort = -1
} else {
target.sort = <number>value;
}
self.sortIndex();
}
break;
case "index":
target.index = <number>value;
break;
case "id":
target.id = <string>value;
break;
}
return true;
}
let proxy = new Proxy(item, watcher);
return proxy;
}

我学到了一些东西,不是很明显。

new Proxy(item, watcher)返回的对象不是"代理"类型(显然没有这样的东西(,而是在本例中创建 ProxyHandler 时指定的 type 属性 MapItem。 但是现在它已经被赋予了处理程序中定义的这些新功能,就像在这种情况下拦截"设置"操作和执行操作的能力一样。

最新更新