Angular 2单击事件回调,不会触发更改检测
我在尝试在Angular 2中的(单击)事件回调函数内执行某些逻辑时遇到了很大的麻烦,而没有触发变化检测.
为什么我不想触发变化检测 回调函数执行简单的动画滚动到顶部.它不会影响其他任何组件,因此我不需要在每个组件中进行变化检测,实际上我真的不希望它开火!由于变化检测在每个组件中都会触发,因此动画在移动设备上的性能极差. 我试过的 我知道我可以使用区域外的代码运行 this._zone.runOutsideAngular(() => { someFunction(); }) 当你想在区域外运行的代码没有被click,keyup,keydown事件等调用时,这很有效. 因为我的组件看起来像…… < button(click)=“doThing()”>在区域外做那件事!< / button> doThing() { this._zone.runOutsideAngular(() => { myFunction(); }) } … myFunction将在区域外运行,但click事件将触发更改检测. 我已经在尽可能多的组件中实现了OnPush变更检测策略. 重要的是,此处不会触发更改检测,但我找不到阻止它的方法. 编辑 解决方法
如上所述,即使将发生单击事件的组件设置为OnPush,仍会导致触发更改检测.
开箱即用的事件处理 @Component({ selector: 'test' template: `<button (click)="onClick($event)">Click me</button>`,changeDetection: ChangeDetectionStrategy.OnPush }) export class MyComponent { onClick(e:Event) { e.preventDefault(); e.stopPropagation(); this._zone.runOutsideAngular(() => { // gets run outside of Angular but parent function still triggers change detection }); return false; /* * change detection always triggered * regardless of what happens above */ } } 大多数时候这可能不是问题,但是当渲染和绘制某些函数的性能是必不可少的时候,我采用的方法是完全绕过Angular的内置事件处理.根据我自己的实验,以下似乎是解决这个问题的最简单,最易维护的方法. 绕过开箱即用的事件处理 这里的想法是使用RxJS手动绑定到我想要的任何事件,在这种情况下是一个点击,使用Observable.fromEvent.此示例还演示了清理事件订阅的实践. import {Component,ElementRef,OnInit,OnDestroy,NgZone} from '@angular/core'; import {Observable} from 'rxjs/Observable'; import {Subscription} from 'rxjs/Subscription'; @Component({ selector: 'test' template: `<button #myButton>Click me</button>`,changeDetection: ChangeDetectionStrategy.OnPush }) export class MyComponent implements OnInit { private _subs:Subscription[] = []; // reference to template variable @ViewChild('myButton') myButton:ElementRef; constructor(private _zone:NgZone){} ngOnInit() { this.manuallyBindToViewEvents(); } manuallyBindToViewEvents() { this.subscribeToMyButton() } subscribeToMyButton() { let sub:Subscription; this._zone.runOutsideAngular(() => { sub = Observable.fromEvent(this.myButton.nativeElement,'click').subscribe(e => { console.log('Yayyyyy! No change detection!'); }) }); this._subs.push(sub); } ngOnDestroy() { // clean up subscriptions this._subs.forEach(sub => sub.unsubscribe()); } } 希望这会对类似情况下的其他人有所帮助. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |