Angular变更检测实验疑问:DOM事件失效与ngZone外变更生效原因
Angular变更检测实验问题解答
Q1:普通DOM事件未生效的原因
你在ngAfterViewInit里先后两次给addBtn.nativeElement.onclick赋值,DOM元素的onclick是单一赋值属性,后赋值的函数会完全替换掉之前的:
- 首先定义的普通DOM事件回调被后续代码覆盖,根本不会执行:
(this.addBtn.nativeElement as HTMLButtonElement).onclick = () => { this.number++; console.log('DOM:', this.number); }; - 紧接着在
runOutsideAngular里重新赋值的onclick才是最终生效的点击回调:this.ngZone.runOutsideAngular(() => { (this.addBtn.nativeElement as HTMLButtonElement).onclick = () => { this.number++; this.cdr.markForCheck(); this.appRef.tick(); console.log('tick:', this.number); }; });
另外你通过fromEvent绑定的RxJS订阅是独立的事件监听,不会被onclick赋值覆盖,所以每次点击会同时触发onclick回调和RxJS订阅,这就是控制台输出tick:和RxJS:交替出现的原因。
Q2:ngZone外修改仍触发变更检测的原因
当你通过Angular模板的(click)="add()"触发add()方法时,这个点击事件是被Angular的Zone.js拦截处理的——Angular会在所有模板绑定的事件回调执行完毕后,自动触发一次变更检测。
即使你在add()内部用runOutsideAngular包裹了number的修改,触发add()的上下文仍然在Angular Zone中,Angular的变更检测机制会在整个事件循环结束时正常执行,所以number的更新会被同步到视图上。
简单来说:模板绑定的事件本身就在Angular的变更检测触发流程里,和你回调内部是否跳出Zone无关。
实验代码参考
模板代码
<h2 class="card-title text-white">{{ number }}</h2> <div class="card-actions justify-end"> <button class="btn btn-warning" (click)="add()">ADD</button> <button class="btn btn-warning" #addBtn> ADD </button> </div>
逻辑代码
add() { this.ngZone.runOutsideAngular(() => { this.number++; console.log('isInAngularZone: ', NgZone.isInAngularZone()); console.log(' Add:', this.number); }); } ngAfterViewInit(): void { // 此回调被后续onclick赋值覆盖,不会执行 (this.addBtn.nativeElement as HTMLButtonElement).onclick = () => { this.number++; console.log('DOM:', this.number); }; this.ngZone.runOutsideAngular(() => { // 最终生效的点击回调 (this.addBtn.nativeElement as HTMLButtonElement).onclick = () => { this.number++; this.cdr.markForCheck(); this.appRef.tick(); console.log('tick:', this.number); }; }); // 独立的RxJS事件监听,不会被覆盖 fromEvent(this.addBtn.nativeElement as HTMLButtonElement, 'click') .subscribe(() => { this.number++; console.log('RxJS:', this.number); }); }
控制台输出
tick: 2 RxJS: 3 tick: 4 RxJS: 5 tick: 6 RxJS: 7 tick: 8 RxJS: 9 tick: 10 RxJS: 11
内容的提问来源于stack exchange,提问作者Acute Wind
相关产品推荐
相关产品推荐

