Tengo un problema de rendimiento que parece que no puedo solucionar. Tengo una búsqueda instantánea pero es algo lenta, ya que comienza a buscar en cada una keyup()
.
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>
Los datos JSON ni siquiera son tan grandes, solo 300 KB, creo que lo que debo lograr es poner un retraso de ~ 1 segundo en la búsqueda para esperar a que el usuario termine de escribir, en lugar de realizar la acción en cada pulsación de tecla. AngularJS hace esto internamente, y después de leer documentos y otros temas aquí no pude encontrar una respuesta específica.
Agradecería cualquier sugerencia sobre cómo puedo retrasar la búsqueda instantánea.
Respuestas:
(Consulte la respuesta a continuación para obtener una solución angular 1.3).
El problema aquí es que la búsqueda se ejecutará cada vez que cambie el modelo, que es cada acción de keyup en una entrada.
Habría formas más limpias de hacer esto, pero probablemente la forma más fácil sería cambiar el enlace para que tenga una propiedad $ scope definida dentro de su controlador en el que opera su filtro. De esa manera puede controlar con qué frecuencia se actualiza esa variable $ scope. Algo como esto:
JS:
HTML:
fuente
ng-model
no funcionará dentro del modal de bootstrap angular-uiACTUALIZAR
Ahora es más fácil que nunca (Angular 1.3), solo agregue una opción antirrebote en el modelo.
<input type="text" ng-model="searchStr" ng-model-options="{debounce: 1000}">
Plunker actualizado:
http://plnkr.co/edit/4V13gK
Documentación sobre ngModelOptions:
https://docs.angularjs.org/api/ng/directive/ngModelOptions
Método antiguo:
Aquí hay otro método sin dependencias más allá del propio ángulo.
Debe establecer un tiempo de espera y comparar su cadena actual con la versión anterior, si ambas son iguales, entonces realiza la búsqueda.
y esto entra en tu opinión:
El saqueador obligatorio: http://plnkr.co/dAPmwf
fuente
En Angular 1.3 haría esto:
HTML:
Controlador:
Básicamente le estás diciendo a angular que corra
myDebouncedFunction()
, cuandomsg
cambia la variable de alcance. El atributong-model-options="{debounce: 1000}"
asegura quemsg
solo se pueda actualizar una vez por segundo.fuente
Ahora podemos configurar las opciones de ng-model-rebote con el tiempo y, cuando se difumina, el modelo debe cambiarse inmediatamente; de lo contrario, al guardarlo tendrá un valor anterior si no se completa el retraso.
fuente
Para aquellos que usan keyup / keydown en el marcado HTML. Esto no usa reloj.
JS
HTML
fuente
Actualizaciones de modelos rebotados / estrangulados para angularjs: http://jsfiddle.net/lgersman/vPsGb/3/
En su caso, no hay nada más que hacer que usar la directiva en el código jsfiddle de esta manera:
Básicamente es un pequeño fragmento de código que consiste en una única directiva angular llamada "ng-ampere-debounce" que utiliza http://benalman.com/projects/jquery-throttle-debounce-plugin/ que se puede conectar a cualquier elemento dom. La directiva reordena los controladores de eventos adjuntos para que pueda controlar cuándo regular los eventos.
Puede usarlo para limitar / eliminar rebotes * actualizaciones angulares del modelo * controlador de eventos angulares ng- [evento] * controladores de eventos jquery
Echa un vistazo: http://jsfiddle.net/lgersman/vPsGb/3/
La directiva será parte del marco de Orangevolt Ampere ( https://github.com/lgersman/jquery.orangevolt-ampere ).
fuente
Solo para usuarios redirigidos aquí:
Como se introdujo en
Angular 1.3
, puede usar el atributo ng-model-options :fuente
Creo que la mejor manera de resolver este problema es usar el complemento de Ben Alman jQuery throttle / debounce . En mi opinión, no hay necesidad de retrasar los eventos de cada campo en su formulario.
Simplemente envuelva su $ scope. $ Watch función de manejo en $ .debounce de esta manera:
fuente
Otra solución es agregar una funcionalidad de retraso a la actualización del modelo. La directiva simple parece hacer un truco:
Uso:
Así que solo usa
delayed-model
en lugar deng-model
y define el deseadodata-delay
.Demostración: http://plnkr.co/edit/OmB4C3jtUD2Wjq5kzTSU?p=preview
fuente
model: '=delayedModel'
está funcionando? ¿O puedes señalarme un enlace donde pueda encontrarlo?element.on('change')
se activa solo en el desenfoque (1) ¿Hay alguna solución? (2) ¿cómo llamar a una función del controlador en el cambio de texto?Resolví este problema con una directiva que básicamente lo que hace es vincular el modelo ng real en un atributo especial que miro en la directiva, luego, usando un servicio antirrebote, actualizo mi atributo de directiva, por lo que el usuario observa la variable que se une a debounce-model en lugar de ng-model.
Uso:
Y en el controlador:
Demostración en jsfiddle: http://jsfiddle.net/6K7Kd/37/
El servicio $ debounce se puede encontrar aquí: http://jsfiddle.net/Warspawn/6K7Kd/
Inspirado por la directiva eventBind http://jsfiddle.net/fctZH/12/
fuente
Angular 1.3 tendrá un rebote ng-model-options, pero hasta entonces, debe usar un temporizador como dijo Josue Ibarra. Sin embargo, en su código, lanza un temporizador cada vez que se presiona una tecla. Además, está usando setTimeout, cuando en Angular uno tiene que usar $ timeout o usar $ apply al final de setTimeout.
fuente
¿Por qué todos quieren usar el reloj? También podría usar una función:
fuente
Creo que la forma más fácil aquí es precargar el json o cargarlo una vez
$dirty
y luego la búsqueda de filtro se encargará del resto. Esto le ahorrará las llamadas http adicionales y es mucho más rápido con datos precargados. La memoria dolerá, pero vale la pena.fuente