这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战
场景
父组件往子组件传递数据的时候,父组件传递了一个数组和字符串过去。
问题
虽然这个数组发生了改变,但是 ngOnChanges() 生命周期内没有检测到数组的变化而只是检测到了字符串的变化,如果只是传递了数组此生命周期不触发。
原因剖析
-
概念理解:
ngOnChanges()绑定属性发生变化时调用
绑定的属性:此场景指的是父组件传递过来的数据,如果传递过来的是值类型则属性是此值,若传递过来的是引用类型则属性是这个引用而非值。 -
原因
字符串在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