栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

角度和去抖动

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

角度和去抖动

针对RC.5更新

使用Angular 2,我们可以

debounceTime()
在窗体控件的
valueChanges
可观察对象上使用RxJS运算符进行反跳:

import {Component}   from '@angular/core';import {FormControl} from '@angular/forms';import {Observable}  from 'rxjs/Observable';import 'rxjs/add/operator/debounceTime';import 'rxjs/add/operator/throttleTime';import 'rxjs/add/observable/fromEvent';@Component({  selector: 'my-app',  template: `<input type=text [value]="firstName" [formControl]="firstNameControl">    <br>{{firstName}}`})export class AppComponent {  firstName        = 'Name';  firstNameControl = new FormControl();  formCtrlSub: Subscription;  resizeSub:   Subscription;  ngonInit() {    // debounce keystroke events    this.formCtrlSub = this.firstNameControl.valueChanges      .debounceTime(1000)      .subscribe(newValue => this.firstName = newValue);    // throttle resize events    this.resizeSub = Observable.fromEvent(window, 'resize')      .throttleTime(200)      .subscribe(e => {        console.log('resize event', e);        this.firstName += '*';  // change something to show it worked      });  }  ngDoCheck() { console.log('change detection'); }  ngonDestroy() {    this.formCtrlSub.unsubscribe();    this.resizeSub  .unsubscribe();  }}

[Plunker](http://plnkr.co/edit/A8Ms99r7sazUeZS90z7K?p=preview)

上面的代码还包括一个如何限制窗口调整大小事件的示例,如@albanx在下面的注释中所要求的。


尽管上面的代码可能是这样做的Angular方式,但效率不高。每个击键和每个调整大小事件(即使它们被去抖和抑制)都将导致更改检测运行。换句话说,
去抖动和节流不影响更改检测运行的频率。(我找到了TobiasBosch的GitHub评论,对此进行了确认。)您可以在运行插入器时看到此消息,并

ngDoCheck()
在键入输入框或调整窗口大小时看到被调用了多少次。(使用蓝色的“
x”按钮在单独的窗口中运行导航按钮,以查看调整大小事件。)

一种更有效的技术是根据事件本身在Angular的“区域”之外创建RxJS
Observables。这样,每次事件触发时都不会调用更改检测。然后,在您的订阅回调方法中,手动触发更改检测-即,您控制何时调用更改检测:

import {Component, NgZone, ChangeDetectorRef, ApplicationRef,         ViewChild, ElementRef} from '@angular/core';import {Observable} from 'rxjs/Observable';import 'rxjs/add/operator/debounceTime';import 'rxjs/add/operator/throttleTime';import 'rxjs/add/observable/fromEvent';@Component({  selector: 'my-app',  template: `<input #input type=text [value]="firstName">    <br>{{firstName}}`})export class AppComponent {  firstName = 'Name';  keyupSub:  Subscription;  resizeSub: Subscription;  @ViewChild('input') inputElRef: ElementRef;  constructor(private ngzone: NgZone, private cdref: ChangeDetectorRef,    private appref: ApplicationRef) {}  ngAfterViewInit() {    this.ngzone.runOutsideAngular( () => {      this.keyupSub = Observable.fromEvent(this.inputElRef.nativeElement, 'keyup')        .debounceTime(1000)        .subscribe(keyboardEvent => {          this.firstName = keyboardEvent.target.value;          this.cdref.detectChanges();        });      this.resizeSub = Observable.fromEvent(window, 'resize')        .throttleTime(200)        .subscribe(e => {          console.log('resize event', e);          this.firstName += '*';  // change something to show it worked          this.cdref.detectChanges();        });    });  }  ngDoCheck() { console.log('cd'); }  ngonDestroy() {    this.keyupSub .unsubscribe();    this.resizeSub.unsubscribe();  }}

[Plunker](http://plnkr.co/edit/E77SzTXvBnaBL4SzyOgh?p=preview)

我使用

ngAfterViewInit()
而不是
ngonInit()
确保
inputElRef
已定义。

detectChanges()
将对此组件及其子组件运行更改检测。如果您希望从根组件运行更改检测(即运行完整的更改检测检查),请
ApplicationRef.tick()
改用。(我
ApplicationRef.tick()
在插件的注释中打了个电话。)请注意,
tick()
将导致
ngDoCheck()
被调用。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/517851.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号