W AngularJS mogę odrzucić model używając opcji ng-model.
ng-model-options="{ debounce: 1000 }"
Jak mogę usunąć model w Angular? Próbowałem poszukać odbicia w dokumentach, ale nie mogłem nic znaleźć.
https://angular.io/search/#stq=debounce&stp=1
Rozwiązaniem byłoby napisanie własnej funkcji debounce, na przykład:
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);
A mój html
<input type=text [value]="firstName" #first (keyup)="firstNameChanged($event, first)">
Ale ja szukam wbudowanej funkcji, czy jest taka w Angular?
javascript
angular
koningdavid
źródło
źródło
Odpowiedzi:
Zaktualizowano dla RC.5
W Angular 2 możemy odrzucić za pomocą operatora RxJS
debounceTime()
navalueChanges
obserwowalnej kontrolce formularza :Plunker
Powyższy kod zawiera również przykład ograniczania zdarzeń związanych ze zmianą rozmiaru okna, zgodnie z pytaniem @albanx w komentarzu poniżej.
Chociaż powyższy kod jest prawdopodobnie sposobem Angulara, nie jest efektywny. Każde naciśnięcie klawisza i każde zdarzenie zmiany rozmiaru, nawet jeśli są usuwane i ograniczane, powoduje uruchomienie wykrywania zmian. Innymi słowy, debouncing i throttling nie wpływają na częstotliwość wykrywania zmian . (Znalazłem komentarz na GitHub autorstwa Tobiasa Boscha, który to potwierdza.) Możesz to zobaczyć po uruchomieniu plunkera i zobaczyć, ile razy
ngDoCheck()
jest wywoływana, gdy wpiszesz w pole wprowadzania lub zmienisz rozmiar okna. (Użyj niebieskiego przycisku „x”, aby uruchomić plunker w osobnym oknie, aby zobaczyć zdarzenia zmiany rozmiaru).Bardziej wydajną techniką jest samodzielne tworzenie RxJS Observables na podstawie zdarzeń, poza „strefą” Angulara. Dzięki temu wykrywanie zmian nie jest wywoływane za każdym razem, gdy wystąpi zdarzenie. Następnie w metodach wywołania zwrotnego subskrypcji ręcznie wyzwalaj wykrywanie zmian - tj. Kontrolujesz, kiedy wywoływane jest wykrywanie zmian:
Plunker
Używam
ngAfterViewInit()
zamiast,ngOnInit()
aby upewnić się, żeinputElRef
jest zdefiniowane.detectChanges()
uruchomi wykrywanie zmian dla tego składnika i jego elementów podrzędnych. Jeśli wolisz uruchomić wykrywanie zmian ze składnika głównego (tj. Uruchomić pełne sprawdzenie wykrywania zmian), użyjApplicationRef.tick()
zamiast tego. (ApplicationRef.tick()
Wstawiłem call to w komentarzach w plunkerze.) Zauważ, że wywołanietick()
spowoduje, żengDoCheck()
zostaniesz wezwany.źródło
.fromEvent()
subskrypcjiJeśli nie chcesz się tym zajmować
@angular/forms
, możesz po prostu użyć RxJSSubject
z powiązaniami zmian.view.component.html
view.component.ts
To wywołuje wykrywanie zmian. Aby poznać sposób, który nie wyzwala wykrywania zmian, zapoznaj się z odpowiedzią Marka.
Aktualizacja
.pipe(debounceTime(300), distinctUntilChanged())
jest potrzebny dla rxjs 6.Przykład:
źródło
.pipe(debounceTime(300), distinctUntilChanged())
jest potrzebny do rxjs 6keyUp
zdarzenie nainput.nativeElement
w sposóbmat-table
, który przestał działać, gdy liczba kolumn została zmienionaMogłaby zostać wdrożona jako dyrektywa
użyj go jak
próbka składnika
źródło
import 'rxjs/add/operator/debounceTime'; import 'rxjs/add/operator/distinctUntilChanged';
naimport { debounceTime, distinctUntilChanged } from 'rxjs/operators';
ithis.model.valueChanges .debounceTime(this.debounceTime) .distinctUntilChanged()
nathis.model.valueChanges .pipe( debounceTime(this.debounceTime), distinctUntilChanged() )
Ponieważ temat jest stary, większość odpowiedzi nie działa w Angular 6/7/8/9 i / lub używa innych bibliotek.
Oto krótkie i proste rozwiązanie dla Angular 6+ z RxJS.
Najpierw zaimportuj niezbędne rzeczy:
Zainicjuj dnia
ngOnInit
:Użyj w ten sposób:
PS: W przypadku bardziej złożonych i wydajnych rozwiązań możesz nadal chcieć sprawdzić inne odpowiedzi.
źródło
Nie jest bezpośrednio dostępny, jak w angular1, ale możesz łatwo bawić się obserwowalnymi NgFormControl i RxJS:
Ten post na blogu wyjaśnia to jasno: http://blog.hardtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html
Tutaj jest to autouzupełnianie, ale działa we wszystkich scenariuszach.
źródło
[...]
jest jednokierunkowym wiązaniem celu. Dlaczego można zgłosić kontenervalueChanges
? nie powinno to być coś. jak(ngFormControl)="..."
?Możesz stworzyć Observable RxJS (v.6), który robi, co chcesz.
view.component.html
view.component.ts
źródło
rsjs/Rx
, miałem błędy podczas korzystania z importu tak, jak go napisałeś ... więc w moim przypadku jest to teraz:import { Observable } from 'rxjs/Rx';
import { Observable } from 'rxjs';
.pipe
połączeniapipe(debounceTime(300), distinctUntilChanged())
Dla osób korzystających lodash, to jest bardzo łatwe do nieczułości żadnej funkcji:
następnie wrzuć coś takiego do swojego szablonu:
źródło
Rozwiązanie z inicjalizacją abonenta bezpośrednio w funkcji zdarzenia:
I html:
źródło
Rozwiązałem to, pisząc dekorator odbicia. Opisany problem można rozwiązać, stosując metodę @debounceAccessor do metody dostępu set właściwości.
Dostarczyłem również dodatkowy dekorator odbicia dla metod, który może być przydatny na inne okazje.
To sprawia, że usunięcie właściwości lub metody jest bardzo łatwe. Parametr to liczba milisekund, które powinno trwać odbicie, 100 ms w przykładzie poniżej.
A oto kod dla dekoratorów:
Dodałem dodatkowy parametr do dekoratora metody, który pozwala wyzwalać metodę PO opóźnieniu odbicia. Zrobiłem to, aby móc na przykład używać go w połączeniu ze zdarzeniami najechania kursorem myszy lub zmiany rozmiaru, gdzie chciałem, aby przechwytywanie miało miejsce na końcu strumienia zdarzeń. Jednak w tym przypadku metoda nie zwróci wartości.
źródło
Możemy stworzyć dyrektywę [debounce], która nadpisuje domyślną funkcję viewToModelUpdate ngModel pustą.
Kod dyrektywy
Jak tego użyć
źródło
Plik HTML:
Plik TS:
źródło
Prostym rozwiązaniem byłoby utworzenie dyrektywy, którą można by zastosować do dowolnego elementu sterującego.
użycie byłoby
źródło
Angular 7
.Spędziłem nad tym wiele godzin, mam nadzieję, że uda mi się uratować trochę czasu komuś innemu. Dla mnie następujące podejście do używania
debounce
na kontrolce jest dla mnie bardziej intuicyjne i łatwiejsze do zrozumienia. Jest oparty na rozwiązaniu dokumentacyjnym angular.io do autouzupełniania, ale z możliwością przechwytywania połączeń bez konieczności wiązania danych z DOM.Plunker
Scenariuszem użycia może być sprawdzenie nazwy użytkownika po jej wpisaniu, aby zobaczyć, czy ktoś już ją wykorzystał, a następnie ostrzeżenie użytkownika.
Uwaga: nie zapomnij,
(blur)="function(something.value)
może to mieć dla Ciebie więcej sensu w zależności od Twoich potrzeb.źródło
DebounceTime w Angular 7 z RxJS v6
Link do źródła
Demo Link
W szablonie HTML
W komponencie
źródło
Możesz również rozwiązać ten problem za pomocą dekoratorów, na przykład używając dekoratora debounce z utils-decorator lib (
npm install utils-decorators
):źródło
To najlepsze rozwiązanie, jakie do tej pory znalazłem. Aktualizuje
ngModel
onblur
idebounce
zgodnie z wypożyczeniem z https://stackoverflow.com/a/47823960/3955513
Następnie w HTML:
Na
blur
modelu jest wyraźnie zaktualizowane przy użyciu zwykłego JavaScript.Przykład tutaj: https://stackblitz.com/edit/ng2-debounce-working
źródło