角度和去抖动

在AngularJS中,我可以通过使用ng-model选项来反跳模型。

ng-model-options="{ debounce: 1000 }"

如何在Angular中对模型进行反跳?我试图在文档中搜索反跳,但找不到任何东西。

一种解决方案是编写我自己的防抖动功​​能,例如:

import {Component, Template, bootstrap} from 'angular2/angular2';

// Annotation section

@Component({

selector: 'my-app'

})

@Template({

url: 'app.html'

})

// Component controller

class MyAppComponent {

constructor() {

this.firstName = 'Name';

}

changed($event, el){

console.log("changes", this.name, el.value);

this.name = el.value;

}

firstNameChanged($event, first){

if (this.timeoutId) window.clearTimeout(this.timeoutID);

this.timeoutID = window.setTimeout(() => {

this.firstName = first.value;

}, 250)

}

}

bootstrap(MyAppComponent);

和我的HTML

<input type=text [value]="firstName" #first (keyup)="firstNameChanged($event, first)">

但是我正在寻找一个内置函数,Angular中有一个吗?

回答:

使用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()被调用。

以上是 角度和去抖动 的全部内容, 来源链接: utcz.com/qa/398892.html

回到顶部