Angular ngOnChanges检测不到输入值的变化 | 更文挑战第6天

1,218 阅读1分钟

这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战

场景

父组件往子组件传递数据的时候,父组件传递了一个数组和字符串过去。

问题

虽然这个数组发生了改变,但是 ngOnChanges() 生命周期内没有检测到数组的变化而只是检测到了字符串的变化,如果只是传递了数组此生命周期不触发。

原因剖析

  1. 概念理解: ngOnChanges() 绑定属性发生变化时调用
    绑定的属性:此场景指的是父组件传递过来的数据,如果传递过来的是值类型属性是此值,若传递过来的是引用类型属性是这个引用而非值

  2. 原因
    字符串在 ngOnChanges() 内可以检测到变化因为它们是值类型,如果改变了 Angular 可检测到;
    但数组和对象是引用类型,ngOnChanges() 只能在它们引用对象改变了才能检测到,它们引用对象的值无论如何变化 Angular 都无法检测到。

解决办法

法1: 将传递过来的数组引用改变,重新创建或者深拷贝一下。

法2: 用 ngDoCheck 检查
在此生命周期中先把第一次传递过来的数组缓存,再传递过来的话比较下,如果不一样则执行想要的操作。

 @Input() form: any;
 ngDoCheck() {
    if(this.form && this._form){
     if( this._form.value.empCode !=  this.form.value.empCode){
      this.searchData(this.form.value.empCode)
      this._form = _.cloneDeep(this.form);
     }
    }else{
      this._form =  _.cloneDeep(this.form);
    }
  }

Setter也只会浅检查

_form: any;
@Input() 
set form(form: any){
    this._form = form
}
get form(){
    return this._form;
}
ngOnChanges(sc: SimpleChanges) {
    console.log("变化了---> ", this.form);
    if(!sc.form) return;
    console.log("ngOnChanges", this.form);
    if (sc.form.firstChange) {
      // 往父组件表单中添加一个控件
      this.addFormCtrl();
      this.addSearchSub();
    }else{
      const val = sc.form.currentValue.value[this.valueKey]
      this.onSearch(val);
    }
    console.log("数据变化的回调", sc.form);
  }

  ngDoCheck() {
    if(this.form && this._form){
      console.log("比较前后的值", this._form.value.empCode, this.form.value.empCode)
     if( this._form.value.empCode !=  this.form.value.empCode){
      console.log("this._form", this._form);
      this.searchData(this.form.value.empCode)
      this._form = _.cloneDeep(this.form);
     }
    }else{
      this._form =  _.cloneDeep(this.form);
    }
  }

更多用法更新于 github