// 给予rxjs设计的组件模型
import {
Input,
OnChanges,
SimpleChanges,
ChangeDetectorRef,
OnInit,
OnDestroy
} from '@angular/core';
import { Observable, merge } from 'rxjs';
import { first, filter, takeWhile } from 'rxjs/operators';
export class BaseComponent implements OnChanges, OnInit, OnDestroy {
@Input() props: Observable<any> = new Observable();
// 需要注销开关
needDestory: boolean = false;
constructor() {}
ngOnChanges(changes: SimpleChanges) {
if ('props' in changes) {
if (!changes['props'].isFirstChange) {
this.__propsHandler();
}
}
}
/**
* 注销
*/
ngOnDestroy() {
this.needDestory = true;
}
ngOnInit() {
this.__propsHandler();
}
// 用户暴露给外部设置props的接口
setProps(props: Observable<any>) {
this.props = merge(this.props, props);
this.__propsHandler();
}
private __propsHandler() {
this.props = merge(
// 添加默认值,解决默认值为null问题
this.props.pipe(first((val, idx) => idx === 0, {})),
this.props
).pipe(
// 去除{}
filter(val => Object.keys(val).length > 0),
// 自动注销
takeWhile(val => !this.needDestory)
);
}
}
建立一个测试组件
import {
Component,
ChangeDetectionStrategy,
ChangeDetectorRef,
OnInit
} from '@angular/core';
import { BaseComponent } from '../base-component';
@Component({
selector: 'base-test',
templateUrl: './base-test.component.html',
styleUrls: ['./base-test.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class BaseTestComponent extends BaseComponent implements OnInit {
constructor() {
super();
}
}
<li>{{(props | async)?.a}}</li>
<li>{{(props | async)?.b}}</li>
<li>{{(props | async)?.c}}</li>
<p>{{props | async | json}}</p>
- 使用测试组件
<base-test [props]="sub2"></base-test>
let i = 0;
setInterval(() => {
this.sub2.next({
a: i++,
b: i++,
c: i++
});
}, 1000);
总结
这样完全绕过angular的changes,完全基于rxjs的核心去做,可能可以去掉ngZone