Arrays 每次数组更改时Typescript激发事件

Arrays 每次数组更改时Typescript激发事件,arrays,typescript,rxjs,Arrays,Typescript,Rxjs,我试图观察typescript 2.3.3中的一个数组,我使用的是rxjs。我的目标是在每次更改数组时运行一个方法。在我告诉你我试过什么之前,让我用一些代码来澄清一下 rows: any[] = [] rows.push('test1') //fired event now rows.splice(0,1) //fire event now rows = [] // fire event now 基本上,如果这个属性发生变化,那么我希望有一个名为的事件 我研究了Rx.Observable,提出

我试图观察typescript 2.3.3中的一个数组,我使用的是rxjs。我的目标是在每次更改数组时运行一个方法。在我告诉你我试过什么之前,让我用一些代码来澄清一下

rows: any[] = []
rows.push('test1') //fired event now
rows.splice(0,1) //fire event now
rows = [] // fire event now
基本上,如果这个属性发生变化,那么我希望有一个名为的事件

我研究了Rx.Observable,提出了两个不同的观点

Rx.Observable.fromthis.rows,然后订阅它,但是订阅从未触发

Rx.Observable.ofthis.rows,然后订阅它,这只触发订阅1次

我认为Rx.Observable是实现这一点的方法,但我不确定如何每次都让它触发事件。 谢谢你的建议


尝试使用扩散而不是推

rows = [...rows,"test"]
看起来可能符合要求。一些初步测试表明,大多数就地数组变体(如splice、sort和push)都会触发代理设置器,因此您可能能够像以下一样轻松地在侧面发出值:

const subj: Subject<TItem> = new Subject(); // whatever TItem is convenient for you
const rows: Array<T> = new Proxy([], {
    set: function(target: Array<T>, idx: PropertyKey, v: T): boolean {
        target[idx] = v;
        this.subj.onNext(/* TItem-typed values here */);
        return true;
    }
});
请注意,令我完全惊讶的是,TypeScript很好地强制执行了新的ProxyArray。。。到数组,所以所有的数组操作仍然是键入的!不利的一面是,您可能会遇到大量事件,特别是处理多次设置的操作,如sort,这在lg n通知中是可以预期的。

我最终创建了一个ObservalArray类,该类将触发事件并在其中包含subscribe方法。我会把这个贴在这里,这样有这个问题的人也可以使用它

export class ObservableArray {
onArrayChanges: EventEmitter<any> = new EventEmitter();
onRemovedItem: EventEmitter<any> = new EventEmitter();
onAddedItem: EventEmitter<any> = new EventEmitter();

onComponentChanges: EventEmitter<any> = new EventEmitter();

length(): number {
    return this.collection.length;
}

private collectionCount: number = 0;
private isStartup:boolean=true;
constructor(public array: any[]) {
    this.onComponentChanges.subscribe(data => {
        this.array = data;
        this.onChanges();
    });
}

private collection: any[] = [];
private subscriptions: any[] = [];

onChanges(): void {
    let collectionModel = new CollectionModel();
    collectionModel.originalValue = this.collection;
    collectionModel.newValue = (this.isStartup)?this.collection:this.array;
    collectionModel.isRecordAdded = this.isAddedItem();
    collectionModel.isRecordRemoved = this.isRemovedItem();

    this.collectionCount = this.collection.length;

    if (this.isAddedItem()) {
        this.onAddedItem.emit(collectionModel);
    }

    if (this.isRemovedItem()) {
        this.onRemovedItem.emit(collectionModel);
    }

    if (this.isChanged()) {
        this.updateCollection();
        this.onArrayChanges.emit(collectionModel);
        this.publish(collectionModel);
        this.isStartup = false;
    }
}
private isChanged(): boolean {
    let isChanged = false;
    if (this.array) {
        isChanged = this.array.length !== this.collectionCount;
    }
    return isChanged || this.isStartup;
}
private isAddedItem(): boolean {
    let isAddedItem = false;
    if (this.array) {
        isAddedItem =this.array.length > this.collectionCount;
    }
    return isAddedItem;
}
private isRemovedItem(): boolean {
    let isRemoved = false;
    if (this.array) {
        isRemoved = this.array.length < this.collectionCount;
    }
    return isRemoved;
}

private updateCollection() {
    this.collection = this.array;
}

    private publish(payload?: any) {
        for (let callback of this.subscriptions) {
            callback(payload);
        }
    }

    subscribe(callback: (payload?: any) => void) {
        this.subscriptions.push(callback);
    }
}

export class CollectionModel {
    originalValue: any[] = [];
    newValue: any[] = [];
    isRecordAdded: boolean = false;
    isRecordRemoved: boolean = false;
}
如果你真的想要,你可以做这个,但在我的情况下,我不认为我需要这样做

我希望这对其他人有帮助