突然想到,vue可以deep watch一个对象,并提供回调
angular怎么搞呢?答:ngDoCheck加一个if,然后深度判断那个对象即可,就是深度判断方法要自己写或者引入什么其他工具库吧
然后搜到了一个很牛的service例子,深度对比服务,主要这个服务还能内部缓存旧值,不需要你自己去找
import { KeyValueChanges, KeyValueDiffer, KeyValueDiffers } from '@angular/core';
export class Customer {
firstName: string;
favoriteColor: string;
}
@Component({
selector: 'my-app',
templateUrl: `./app.component.html`
})
export class AppComponent {
private customerDiffer: KeyValueDiffer<string, any>;
private customer: Customer;
constructor(private differs: KeyValueDiffers) {}
ngOnInit(): void {
this.customer = new Customer();
this.customerDiffer = this.differs.find(this.customer).create();
}
customerChanged(changes: KeyValueChanges<string, any>) {
console.log('changes');
/* If you want to see details then use
changes.forEachRemovedItem((record) => ...);
changes.forEachAddedItem((record) => ...);
changes.forEachChangedItem((record) => ...);
*/
}
ngDoCheck(): void {
const changes = this.customerDiffer.diff(this.customer);
if (changes) {
this.customerChanged(changes);
}
}
}
stackoverflow.com/questions/4…
但是,ngDoCheck 会被高频调用,虽说通常性能没问题,但如果用不好,还是可能出现性能问题的。考虑回rxjs,还是更接近这种主动推送的做法,应当是更好的,如果要进一步做深度监听的话,就配合上面发现的differ服务吧,这是我实现的小例子,用setter监听,用subject推送
/**
* 监听指定的属性 返回可订阅的 watcher 类似 vue
* 通过 takeUntil 自动取消订阅
* @param dataParent 对象引用
* @param key 属性名
* @param destory$ 组件实例销毁信号
* @returns
*/
export function watchData$$(dataParent: unknown, key: string, destory$: Subject<void>) {
const watcher$ = new Subject<{newVal, oldVal}>();
let value = dataParent[key]; // 用闭包将值私藏起来 同时暴露get方法也能参与变更检测
Object.defineProperty(dataParent, key, {
get() { return value },
set(newVal) {
const oldVal = value;
value = newVal;
watcher$.next({newVal, oldVal});
}
});
return watcher$.pipe(takeUntil(destory$));
}