手动触发ngOnChanges方案

本文介绍了一种使用自定义类实现的数据变化监听方法,适用于数组和对象结构。通过示例展示了如何监听数组和对象内部数据的变化,并提供了简易的实现代码。
// 数组
class RenderIterableChange<T> {
  private _differ: IterableDiffer<T>;
  private data: NgIterable<T>;
  private change$: Subject<IterableChanges<T>> = new Subject();

  constructor(
    // 数据
    data: { [key: number]: any },
    // 变化
    private _differs: IterableDiffers
  ) {
    // 初始化时先执行一次changes
    this.doChanges(data, true);
  }

  private doCheck(): void {
    if (this._differ) {
      let changes = this._differ.diff(this.data);
      if (changes) {
        // 变化监听
        this.change$.next(changes);
      }
    }
  }
  // 首次调用一次 之后每次变化调用
  doChanges(data: any, isFirst: boolean = false): void {
    // 如果不是首次变化 先检测变化
    if (!isFirst) {
      this.doCheck();
    }
    this._differ = this._differs.find(data).create();
    this.data = data;
    // 如果是首次变化 后检测变化
    if (isFirst) {
      this.doCheck();
    }
  }

  onChanges(): Subject<IterableChanges<T>> {
    return this.change$;
  }
}
// key-value
class RenderKeyValueChange<T> {
  private _differ: KeyValueDiffer<string, T>;
  private data: { [key: string]: T };
  private change$: Subject<KeyValueChanges<string, any>> = new Subject();
  constructor(
    // 数据
    data: { [key: string]: T },
    // 变化
    private _differs: KeyValueDiffers
  ) {
    // 初始化时先执行一次changes
    this.doChanges(data, true);
  }
  private doCheck(): void {
    if (this._differ) {
      let changes = this._differ.diff(this.data);
      if (changes) {
        // 变化监听
        this.change$.next(changes);
      }
    }
  }
  // 首次调用一次 之后每次变化调用
  doChanges(data: any, isFirst: boolean = false): void {
    // 如果不是首次变化 先检测变化
    if (!isFirst) {
      this.doCheck();
    }
    this._differ = this._differs.find(data).create();
    this.data = data;
    // 如果是首次变化 后检测变化
    if (isFirst) {
      this.doCheck();
    }
  }
  // 监听变化
  onChanges(): Subject<KeyValueChanges<string, T>> {
    return this.change$;
  }
}
复制代码
  • use

监听object变化

let a = { i: 2 };
let b = { i: 2 };
let c = { i: 2 };
let d = { i: 2 };
let list = { a: a, b: b, c: c, d: d };
let change = new RenderKeyValueChange(list, this._differs);
change.change$.subscribe(res => {
  console.log(res);
});
a.i = 333;
list.a = c;
change.onChanges(list);
复制代码

监听数组变化

let a = { i: 2 };
let b = { i: 2 };
let c = { i: 2 };
let d = { i: 2 };
let list = [a, b, c, d];
let change = new RenderIterableChange(list, this._iterableDiffers);
change.onChanges().subscribe(res => {
  // 改变监听
  console.log(res);
});
a.i = 333;
list[1] = c;
change.doChanges(list);
复制代码

缺点,只能检测引用变化,不能检测真实值的改变 下面着手优化一下。

// rich-text-editor.component.ts import { Component, Input, Output, EventEmitter, AfterViewInit, ViewEncapsulation, ViewChild, ElementRef, } from "@angular/core"; import { EditorComponent } from "@tinymce/tinymce-angular"; @Component({ selector: "ng-tinymce-editor", templateUrl: `./ng-tinymce-editor.component.html`, styleUrls: ["./ng-tinymce-editor.component.less"], encapsulation: ViewEncapsulation.None, }) export class TinyMceComponent implements AfterViewInit { @ViewChild('tinyEditor') editor: EditorComponent; @Input() content: string @Output() contentChange = new EventEmitter<string>(); @Output() editorInit = new EventEmitter<string>(); public init = { height: 300, // 编辑器高度 suffix: ".min", // 指定资源文件后缀 menu: false, // 控制编辑器顶部菜单栏的显示或隐藏 inline: false, menubar: false, // 顶部功能栏(菜单栏)的显示或隐藏 statusbar: false, // 底部状态栏的显示或隐藏 branding: false, // 右下角品牌信息(如“Powered by Tiny”)的显示或隐藏 base_url: "/tinymce", // 指定 Tinymce 资源文件的基路径 placeholder: "请在这里输入内容", plugins: "advlist autolink lists link image charmap print preview anchor", // 编辑器加载的插件 toolbar: "bold | forecolor", // 工具栏的布局和功能按钮 paste_data_images: false, init_instance_callback: (editor: any) => { if (this.content) { editor.setContent(this.content); } }, }; handleContentChange($event) { const content = $event.event.target.getContent(); this.contentChange.emit(content) } // 获取初始化的值 onEditorInit($event) { const content = $event.editor.setContent(this.content) this.editorInit.emit(content) } ngAfterViewInit(): void {} }
06-19
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值