我想研究一下变化检测的工作原理,在父组件和子组件中使用变化检测的数组(子)。OnPush
. 试图用拼接或推送的方式改变数组,还是会影响子组件模板。为什么这样做是可行的,即使是在引用了 @Input
不会改变?
我的父组件.ts
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, AfterViewInit {
children = [1,2,3,4,5,6,7,8,9]
emit(j) {
this.children.splice(j, 1);
}
}
母html
<div>
<app-multi [input]="children" (output)="emit($event)"></app-multi>
</div>
我的子组件.ts
@Component({
selector: 'app-multi',
templateUrl: './multi.component.html',
styleUrls: ['./multi.component.css'],
changeDetection:ChangeDetectionStrategy.OnPush
})
export class MultiComponent implements OnInit,OnChanges,DoCheck,AfterViewInit{
@Input('input') ele = [];
data = [];
@Output('output') outputEmi = new EventEmitter();
ngOnInit() {
this.data = this.ele;
}
clicks(value){
this.outputEmi.emit(value);
}
}
子项目
{{name.name}}
<table>
<tbody>
<tr>
<td *ngFor="let head of data; let i = index;">
<span>{{head}}</span>
<button class="delete" (click)="clicks(i)">x</button>
</td>
</tr>
</tbody>
</table>
根据我的理解,你的问题是你想知道为什么变化检测工作,即使是参考的是 @Input
不改变?
在变更检测策略设置为 OnPush
子组件只检查它的模板绑定,有几个原因。
@Input()
价值改变@Output
在你的情况下,第二点和最后一点发生了,因为这个 *ngFor
内的子模板再次运行,发现输入的数组中多了一个新的内容。
一句话,所以即使数组的引用保持不变,而你的 @Input()
并没有改变引用,但仍然有一个变化检测被触发,因为子组件收到一个绑定的 (click)
并发出 @Output
.
如果你要更新你的代码,而不使用 @Output()
变化检测仍然有效,因为一个事件被绑定到模板上。
clicks(value){
this.input.splice(value, 1);
}
为了触发变化检测,当它是OnPush时,你必须改变引用,所以如果你使 splice
它不会改变引用,只会更新现有的数组,所以我鼓励你做的是 filter
方法而不是 splice
但如果你必须使用拼接,记得要像这样更新参考资料
this.children.splice(i,j);
this.children = [...this.children]