我有一个性能问题,似乎无法解决。我有一个即时搜索功能,但它有点滞后,因为它在每次 "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>
JSON 数据并不大,只有 300KB,我想我需要实现的是在搜索时设置 ~1 秒的延迟,等待用户键入完毕,而不是在每次按键时执行操作。AngularJS 内部是这样做的,在阅读了这里的文档和其他主题后,我找不到具体的答案。
如果能告诉我如何延迟即时搜索,我将不胜感激。
更新
现在比以往(Angular 1.3)更简单了,只需在模型上添加去抖选项即可。
<input type="text" ng-model="searchStr" ng-model-options="{debounce: 1000}">
。
更新了 plunker: http://plnkr.co/edit/4V13gK
关于 ngModelOptions 的文档:
https://docs.angularjs.org/api/ng/directive/ngModelOptions
旧方法:
这里是另一种方法,除了 angular 本身之外,它不依赖任何其他因素。
你需要设置一个超时时间,然后将当前字符串与过去的版本进行比较,如果两者相同,它就会执行搜索。
$scope.$watch('searchStr', function (tmpStr)
{
if (!tmpStr || tmpStr.length == 0)
return 0;
$timeout(function() {
// if searchStr is still the same..
// go ahead and retrieve the data
if (tmpStr === $scope.searchStr)
{
$http.get('//echo.jsontest.com/res/'+ tmpStr).success(function(data) {
// update the textarea
$scope.responseData = data.res;
});
}
}, 1000);
});
并将其输入视图:
<input type="text" data-ng-model="searchStr">
<textarea> {{responseData}} </textarea>
(有关 Angular 1.3 解决方案,请参见下面的答案)。
这里的问题是,每次模型发生变化,也就是输入上的每次按键操作,都会执行搜索。
有一些更简洁的方法可以做到这一点,但最简单的方法可能是切换绑定,这样您就可以在控制器中定义一个 $scope 属性,在该属性上执行过滤器操作。这样您就可以控制 $scope 变量的更新频率。类似这样
JS:
var App = angular.module('App', []);
App.controller('DisplayController', function($scope, $http, $timeout) {
$http.get('data.json').then(function(result){
$scope.entries = result.data;
});
// This is what you will bind the filter to
$scope.filterText = '';
// Instantiate these variables outside the watch
var tempFilterText = '',
filterTextTimeout;
$scope.$watch('searchText', function (val) {
if (filterTextTimeout) $timeout.cancel(filterTextTimeout);
tempFilterText = val;
filterTextTimeout = $timeout(function() {
$scope.filterText = tempFilterText;
}, 250); // delay 250 ms
})
});
HTML:
<input id="searchText" type="search" placeholder="live search..." ng-model="searchText" />
<div class="entry" ng-repeat="entry in entries | filter:filterText">
<span>{{entry.content}}</span>
</div>
针对 angularjs 的去重/节流模型更新 :
在您的案例中,除了在 jsfiddle 代码中使用这样的指令外,没有什么可做的了:
<input
id="searchText"
type="search"
placeholder="live search..."
ng-model="searchText"
ng-ampere-debounce
/>
这基本上是一小段代码,由一个名为"ng-ampere-debounce"的单个 angular 指令组成,它使用 http://benalman.com/projects/jquery-throttle-debounce-plugin/,可以附加到任何 dom 元素。该指令对附加的事件处理程序进行了重新排序,以便控制何时对事件进行节流。
您可以使用它来节流/弹跳
查看 :
该指令将成为 Orangevolt Ampere 框架 (https://github.com/lgersman/jquery.orangevolt-ampere) 的一部分。