当前位置: 首页 > 知识库问答 >
问题:

角2和防抖

有翰海
2023-03-14

在AngularJS中,我能够使用ng-model选项来防抖模型。

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

如何在Angular中给模型去抖?< br >我试图在文档中搜索去抖,但什么也找不到。

https://angular.io/search/#stq=debounce

解决方案是编写自己的去抖动函数,例如:

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);

和我的网页

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

但我正在寻找内置功能,Angular中有吗?

共有3个答案

宇文和昶
2023-03-14

由于这个主题很老,大多数答案在Angular 6-13上不起作用和/或使用其他库。
因此,这里有一个使用RxJS的Angular 6的简短而简单的解决方案。

首先导入必要的东西:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject, Subscription } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';

实现ngOnInitngOnDestroy

export class MyComponent implements OnInit, OnDestroy {
  public notesText: string;
  public notesModelChanged: Subject<string> = new Subject<string>();
  private notesModelChangeSubscription: Subscription

  constructor() { }

  ngOnInit() {
    this.notesModelChangeSubscription = this.notesModelChanged
      .pipe(
        debounceTime(2000),
        distinctUntilChanged()
      )
      .subscribe(newText => {
        this.notesText = newText;
        console.log(newText);
      });
  }

  ngOnDestroy() {
    this.notesModelChangeSubscription.unsubscribe();
  }
}

使用这种方式:

<input [ngModel]='notesText' (ngModelChange)='notesModelChanged.next($event)' />

注:对于更复杂、更高效的解决方案,您可能仍需要检查其他答案。

甄阿苏
2023-03-14

如果您不想处理@angering/form,您可以只使用带有更改绑定的RxJS主题

<input [ngModel]='model' (ngModelChange)='changed($event)' />
import { Subject } from 'rxjs';
import { Component }   from '@angular/core';
import 'rxjs/add/operator/debounceTime';

export class ViewComponent {
    model: string;
    modelChanged: Subject<string> = new Subject<string>();

    constructor() {
        this.modelChanged
            .debounceTime(300) // wait 300ms after the last event before emitting last event
            .distinctUntilChanged() // only emit if value is different from previous value
            .subscribe(model => this.model = model);
    }

    changed(text: string) {
        this.modelChanged.next(text);
    }
}

这确实会触发变化检测。对于不触发变化检测的方法,请查看Mark的答案。

<代码>。rxjs 6需要pipe(debounceTime(300),distinctUntilChanged())。

例子:

   constructor() {
        this.modelChanged.pipe(
            debounceTime(300), 
            distinctUntilChanged())
            .subscribe(model => this.model = model);
    }
张唯
2023-03-14

针对 RC.5 进行了更新

对于角度 2,我们可以在表单控件的值上使用 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();
  }
} 

插入器

正如@albanx在下面的评论中所问的那样,上面的代码还包括一个如何限制窗口调整事件的示例。

虽然上面的代码可能是有角度的方法,但效率不高。每一次击键和每一次调整大小事件,即使它们被去抖和抑制,也会导致变化检测运行。换句话说,去抖动和节流不会影响更改检测运行的频率。(我发现Tobias Bosch的GitHub评论证实了这一点。)您可以在运行plunker时看到这一点,当您在输入框中键入内容或调整窗口大小时,您会看到< code>ngDoCheck()被调用了多少次。(使用蓝色的“x”按钮在一个单独的窗口中运行plunker来查看resize事件。)

一个更有效的技术是从Angular的“区域”之外的事件中自己创建RxJS可观察值。这样,每次事件触发时就不会调用更改检测。然后,在您的subscribe回调方法中,手动触发变更检测–即,您控制何时调用变更检测:

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();
  }
} 

插入器

我使用< code > ngafterviewit()而不是< code>ngOnInit()来确保定义了< code>inputElRef。

detectChange()将对该组件及其子组件运行更改检测。如果您更愿意从根组件运行更改检测(即运行完整的更改检测检查),请改用ApplicationRef.tick()。(我在柱塞的注释中调用了ApplicationRef.tick()。)请注意,调用tick()将导致调用ngDoCheck()

 类似资料:
  • 在我的模板中,我有一个字段和两个按钮: 在我的组件. ts文件中,我有: 这个。update()函数将myValue放入大JSON对象的适当字段中,并将其发送到服务器。 问题:当用户在短时间内点击10次加号/减号按钮时,将发送10次请求。但我只想发送一次请求-在上次单击后0.5秒。怎么做?

  • 我遇到了这个githttps://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md,它展示了开发人员如何通过添加“被动监听器”来提高滚动性能。我第一次看到它是在我的chrome向我显示警告时(确切的警告是“由于主线程繁忙,‘触摸启动’输入事件的处理延迟了126毫秒”。考虑将事件处理程序标记为“被动”,以使页面更具响应性。

  • 我正在尝试使用Spring Security(4.1.3)和Angular 2.0.1实现CSRF保护 相关话题的来源很多,但我找不到明确的说明。有些说法甚至相互矛盾。 我读过关于springs的操作方法(尽管指南中描述了Angular 1 way)Spring Security guide,其中包含Angular,即

  • html SystemJS配置 家庭组件 问-我如何修复这个未知元素的问题?谢了!

  • 问题内容: 我是否正确使用ng-cloak?在chrome中,带有帮助文本的div在被隐藏之前会闪烁。如果我加 到锚点。我没有得到这样的闪光。在我的角度类中,hideHelp默认为true。 问题答案: 如果您正在使用,则必须在其中添加特定的样式(以便它们在AngularJS加载之前起作用)。 https://docs.angularjs.org/api/ng/directive/ngCloak

  • 2. 角色 2.1 如何创建角色? 进入“角色”管理页面之后,选择“创建新角色”,即可创建新的角色。 2.2 如何给角色添加权限? 选择创建好的角色,给角色添加权限。