在AngularJS中,我可以使用ng-model选项去抖模型 .
ng-model-options="{ debounce: 1000 }"
如何在Angular中去抖模型?我试图在文档中搜索debounce,但我找不到任何东西 .
https://angular.io/search/#stq=debounce&stp=1
解决方案是编写我自己的去抖函数,例如:
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中有一个吗?
16 回答
Updated for RC.5
使用Angular 2,我们可以在窗体控件的
valueChanges
observable上使用RxJS运算符debounceTime()
进行去抖:Plunker
上面的代码还包括如何限制窗口调整大小事件的示例,如@albanx在下面的评论中所述 .
虽然上面的代码可能是Angular方式,但效率不高 . 每次击键和每次调整大小事件,即使它们被去抖动和限制,也会导致变化检测运行 . 换句话说, debouncing and throttling do not affect how often change detection runs . (我发现Tobias Bosch确认了一个GitHub comment确认了这一点 . )当您运行plunker时,您可以看到这一点,当您在输入框中输入或调整窗口大小时,您会看到
ngDoCheck()
被调用了多少次 . (使用蓝色"x"按钮在单独的窗口中运行plunker以查看调整大小事件 . )更有效的技术是在Angular的“区域”之外的事件中自己创建RxJS Observable . 这样,每次事件触发时都不会调用更改检测 . 然后,在您的订阅回调方法中,手动触发更改检测 - 即,您可以控制何时调用更改检测:
Plunker
我使用
ngAfterViewInit()
而不是ngOnInit()
来确保定义inputElRef
.detectChanges()将对此组件及其子组件运行更改检测 . 如果您希望从根组件运行更改检测(即,运行完整更改检测检查),请改用ApplicationRef.tick() . (我在plunker的注释中调用了
ApplicationRef.tick()
. )注意调用tick()
将导致ngDoCheck()
被调用 .如果您不想处理
@angular/forms
,可以使用带有更改绑定的RxJS Subject .view.component.html
view.component.ts
这确实触发了变化检测 . For a way that doesn't trigger change detection, check out Mark's answer.
更新
rxjs 6需要
.pipe(debounceTime(300), distinctUntilChanged())
.例:
不能像angular1那样直接访问,但你可以轻松地使用NgFormControl和RxJS observables:
这篇博客文章清楚地解释了这一点:http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
这是一个自动完成,但它适用于所有场景 .
它可以作为指令实施
用它就像
组件样本
您可以创建一个RxJS(v.6)Observable,它可以做任何你喜欢的事情 .
view.component.html
view.component.ts
对于任何使用lodash的人来说,任何功能都非常容易:debounce
然后把这样的东西扔到你的模板中:
我通过编写debounce装饰器解决了这个问题 . 所描述的问题可以通过将@debounceAccessor应用于属性的set访问器来解决 .
我还为方法提供了额外的debounce装饰器,这对其他场合非常有用 .
这使得去抖属性或方法变得非常容易 . 该参数是去抖应该持续的毫秒数,在下面的示例中是100毫秒 .
这是装饰器的代码:
我为方法装饰器添加了一个额外的参数,让你在去抖延迟后触发方法 . 我做到了这一点,所以我可以在使用鼠标悬停或调整大小事件时使用它,我希望在事件流结束时进行捕获 . 但是,在这种情况下,该方法不会返回值 .
我们可以创建一个[debounce]指令,该指令用空的覆盖ngModel的默认viewToModelUpdate函数 .
指令代码
如何使用它
简单的解决方案是创建一个可以应用于任何控件的指令 .
用法是
花了好几个小时,希望我可以节省一些时间 . 对我来说,在控件上使用
debounce
的以下方法对我来说更直观,更容易理解 . 它 Build 在angular.io docs解决方案的基础上,用于自动完成,但是我能够拦截调用,而不必依赖于将数据绑定到DOM .Plunker
一个用例场景可能是在输入用户名之后检查用户名,看看有人是否已经使用了用户名,然后警告用户 .
注意:不要忘记,根据您的需要,
(blur)="function(something.value)
可能对您更有意义 .这是我迄今为止找到的最佳解决方案 . 更新
blur
blur
和debounce
借来自https://stackoverflow.com/a/47823960/3955513
然后在HTML中:
在
blur
上,使用普通javascript显式更新模型 .示例:https://stackblitz.com/edit/ng2-debounce-working
由于主题是旧的,大多数答案 don't work 在 Angular 6 .
因此,对于带有RxJS的Angular 6,这是一个简短而简单的解决方案 .
首先导入必要的东西:
在
ngOnInit
上初始化:使用这种方式:
P.S . :对于更复杂和有效的解决方案,您可能仍需要检查其他答案 .
对于Reactive Forms和Angular v2(最新)加v4下的处理,请查看:
https://github.com/angular/angular/issues/6895#issuecomment-290892514
希望很快就会对这些事情提供原生支持......
在事件函数中直接初始化订户的解决方案
和HTML:
HTML文件:
TS档案: