Mam problem z wydajnością, którego nie mogę rozwiązać. Mam wyszukiwanie natychmiastowe, ale jest trochę opóźnione, ponieważ zaczyna szukać na każdymkeyup()
.
JS:
var App = angular.module('App', []);
App.controller('DisplayController', function($scope, $http) {
$http.get('data.json').then(function(result){
$scope.entries = result.data;
});
});
HTML:
<input id="searchText" type="search" placeholder="live search..." ng-model="searchText" />
<div class="entry" ng-repeat="entry in entries | filter:searchText">
<span>{{entry.content}}</span>
</div>
Dane JSON nie są nawet tak duże, tylko 300KB, myślę, że to, co muszę zrobić, to ustawić opóźnienie około 1 sekundy w wyszukiwaniu, aby poczekać, aż użytkownik skończy pisać, zamiast wykonywać akcję po każdym naciśnięciu klawisza. AngularJS robi to wewnętrznie i po przeczytaniu dokumentów i innych tematów na ten temat nie mogłem znaleźć konkretnej odpowiedzi.
Byłbym wdzięczny za wszelkie wskazówki, jak mogę opóźnić wyszukiwanie natychmiastowe.
Odpowiedzi:
(Zobacz odpowiedź poniżej dla rozwiązania Angular 1.3.)
Problem polega na tym, że wyszukiwanie będzie wykonywane za każdym razem, gdy model się zmieni, czyli przy każdej akcji klucza na wejściu.
Byłoby na to czystszy sposób, ale prawdopodobnie najłatwiejszym sposobem byłoby przełączenie powiązania tak, aby mieć zdefiniowaną właściwość $ scope wewnątrz kontrolera, na którym działa filtr. W ten sposób możesz kontrolować, jak często ta zmienna $ scope jest aktualizowana. Coś takiego:
JS:
HTML:
źródło
ng-model
nie będzie działał w module bootstrap angular-uiAKTUALIZACJA
Teraz jest to łatwiejsze niż kiedykolwiek (Angular 1.3), wystarczy dodać opcję odbicia w modelu.
<input type="text" ng-model="searchStr" ng-model-options="{debounce: 1000}">
Zaktualizowany plunker:
http://plnkr.co/edit/4V13gK
Dokumentacja na temat ngModelOptions:
https://docs.angularjs.org/api/ng/directive/ngModelOptions
Stara metoda:
Oto inna metoda bez zależności poza samym angularem.
Musisz ustawić limit czasu i porównać bieżący ciąg z poprzednią wersją, jeśli obie są takie same, wykonuje wyszukiwanie.
i to idzie do twojego widoku:
Obowiązkowy plunker: http://plnkr.co/dAPmwf
źródło
W Angular 1.3 zrobiłbym to:
HTML:
Kontroler:
Zasadniczo mówisz angularowi, aby działał
myDebouncedFunction()
, gdymsg
zmienna zasięgu się zmienia. Atrybutng-model-options="{debounce: 1000}"
zapewnia, żemsg
aktualizacja może odbywać się tylko raz na sekundę.źródło
Teraz możemy ustawić odbijanie opcji ng-model-options w czasie, a gdy rozmycie, model musi zostać natychmiast zmieniony, w przeciwnym razie po zapisaniu będzie miał starszą wartość, jeśli opóźnienie nie zostanie zakończone.
źródło
Dla tych, którzy używają keyup / keydown w znacznikach HTML. To nie używa zegarka.
JS
HTML
źródło
Odrzucone / ograniczone aktualizacje modelu dla angularjs: http://jsfiddle.net/lgersman/vPsGb/3/
W twoim przypadku nie pozostaje nic więcej do zrobienia niż użycie dyrektywy w kodzie jsfiddle w następujący sposób:
Zasadniczo jest to mały fragment kodu składający się z pojedynczej dyrektywy kątowej o nazwie „ng-ampere-debounce” wykorzystującej http://benalman.com/projects/jquery-throttle-debounce-plugin/, który można dołączyć do dowolnego elementu dom. Dyrektywa zmienia kolejność dołączonych programów obsługi zdarzeń, dzięki czemu może kontrolować, kiedy ograniczać zdarzenia.
Możesz go użyć do dławienia / usuwania * aktualizacji kątowych modelu * obsługi zdarzeń kątowych ng- [zdarzenie] * obsługi zdarzeń jquery
Spójrz: http://jsfiddle.net/lgersman/vPsGb/3/
Dyrektywa będzie częścią struktury Orangevolt Ampere ( https://github.com/lgersman/jquery.orangevolt-ampere ).
źródło
Tylko dla użytkowników przekierowanych tutaj:
Jak przedstawiono w
Angular 1.3
, możesz użyć atrybutu ng-model-options :źródło
Uważam, że najlepszym sposobem rozwiązania tego problemu jest użycie wtyczki jQuery throttle / debounce Bena Almana . Moim zdaniem nie ma potrzeby opóźniania wydarzeń z każdego pola w Twoim formularzu.
Po prostu opakuj funkcję obsługi $ scope. $ Watch w $ .debounce w następujący sposób:
źródło
Innym rozwiązaniem jest dodanie funkcji opóźnienia do aktualizacji modelu. Wydaje się, że prosta dyrektywa działa:
Stosowanie:
Więc po prostu użyj
delayed-model
zamiastng-model
i zdefiniuj pożądanedata-delay
.Demo: http://plnkr.co/edit/OmB4C3jtUD2Wjq5kzTSU?p=preview
źródło
model: '=delayedModel'
to działa? Czy możesz wskazać mi łącze, w którym mogę je znaleźć?element.on('change')
wyzwala się tylko po rozmyciu. (1) Czy jest jakieś obejście? (2) jak wywołać funkcję kontrolera przy zmianie tekstu?Rozwiązałem ten problem za pomocą dyrektywy, która zasadniczo polega na wiązaniu rzeczywistego modelu ng ze specjalnym atrybutem, który obserwuję w dyrektywie, a następnie za pomocą usługi debounce aktualizuję atrybut dyrektywy, więc użytkownik obserwuje zmienną, która on wiąże się z modelem odbicia zamiast modelu ng.
Stosowanie:
A w kontrolerze:
Demo w jsfiddle: http://jsfiddle.net/6K7Kd/37/
usługę $ debounce można znaleźć tutaj: http://jsfiddle.net/Warspawn/6K7Kd/
Zainspirowany dyrektywą finalBind http://jsfiddle.net/fctZH/12/
źródło
Angular 1.3 będzie miał odbicie opcji ng-model-options, ale do tego czasu musisz używać timera, jak powiedział Josue Ibarra. Jednak w swoim kodzie uruchamia licznik czasu przy każdym naciśnięciu klawisza. Używa również setTimeout, kiedy w Angular trzeba użyć $ timeout lub użyć $ apply na końcu setTimeout.
źródło
Dlaczego wszyscy chcą używać zegarka? Możesz także użyć funkcji:
źródło
Myślę, że najłatwiejszym sposobem jest wstępne załadowanie json lub załadowanie go raz,
$dirty
a wyszukiwanie filtru zajmie się resztą. Pozwoli to zaoszczędzić dodatkowe wywołania http i jest znacznie szybsze dzięki wstępnie załadowanym danym. Pamięć będzie bolała, ale warto.źródło