完全基于rxjs的组件开发探索

262 阅读1分钟
// 给予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