首页 > 解决方案 > 在 TypeScript 中使用代理作为 object.property 观察者

问题描述

我已经编写了一种排序地图类型的对象 (SortedMap),它存储实现此 MapItem 接口的对象。

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

当有人在其内部存储中更改其中一个 MapItems 的排序属性时,我希望 SortedMap 使用它的集合,所以当我看到排序发生变化时,我试图触发一个手段。当一个新项目被添加到集合中时,我想添加某种“观察者”来查找任何集合 MapItem.sort 属性中的更改。

我想我可以按照 MDN Proxy 上描述的模式使用代理来做到这一点,所以写了这个函数,当一个新项目添加到 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 文档本身几乎不存在 Proxy 的文档。

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

标签: typescript

解决方案


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

    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 时指定的类型属性,MapItem。但是现在它已经被赋予了在处理程序中定义的这些新功能,例如在这种情况下拦截“设置”操作并执行某些操作的能力。


推荐阅读