我正在尝试在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.from(this.rows)
然后订阅它,但订阅永远不会被解雇。 Rx.Observable.of(this.rows)
然后订阅它,这只会激活订阅一次。
我认为Rx.Observable
是前往这里的方式,但我不确定如何每次都举起这个事件。
谢谢你的建议
答案 0 :(得分:2)
看起来Proxy
可能符合要求。一些初步测试表明,大多数就地Array
变异器(如splice
,sort
和push
)执行触发Proxy
设置器,因此您可以像在以下一样轻松地发出值:
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强制new Proxy(Array<T>, ...)
到Array<T>
,因此所有数组操作仍然是键入的!在缺点方面,您可能会遇到事件,特别是处理多次设置的操作,例如sort
,您可以期待O(n lg n)
次通知。
答案 1 :(得分:0)
尝试使用&#34;传播&#34;而不是&#34;推&#34;
rows = [...rows,"test"]
答案 2 :(得分:0)
我最终创建了一个ObservableArray
类,它将触发事件并在其中有一个订阅方法。我会在这里发布这个,以便有这个问题的人也可以使用它。
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;
}
如果你真的想要你可以做到这一点ObservableArray<T>
但是在我的情况下,我认为我不需要这样做。
我希望这有助于其他人。 :)