この問題の簡単な解決策はこちらです: jsfiddle.net/nZdgm
$ scope.searchTextフィールドのテキストを含む何かに基づいて、フィルターされたリスト($ scope.filteredList)として公開するリスト($ scope.list)があるとします。 フォームは次のようになります(現時点ではスロットルチェックボックスに注意しないでください)。
<div data-ng-app='App'> <div data-ng-controller="MyCtrl"> <form> <label for="searchText">Search Text:</label> <input data-ng-model="searchText" name="searchText" /> <input type="checkbox" data-ng-model="throttle"> Throttle <label>You typed:</label> <span>{{searchText}}</span> </form> <ul><li data-ng-repeat="item in filteredList">{{item}}</li></ul> </div> </div>
典型的なシナリオは、検索フィールドを観察して即座に応答することです。 ろ過方法:
var filterAction = function($scope) { if (_.isEmpty($scope.searchText)) { $scope.filteredList = $scope.list; return; } var searchText = $scope.searchText.toLowerCase(); $scope.filteredList = _.filter($scope.list, function(item) { return item.indexOf(searchText) !== -1; }); };
コントローラーは次のように$ watchを設定します
$scope.$watch('searchText', function(){filterAction($scope);});
このアプローチは、フィールドに入力するたびにフィルタリングをトリガーします。 状況を改善するために、underscore.jsに組み込まれているdebounce関数を使用します。 この関数は非常に単純です。実行する関数とミリ秒単位の時間を指定します。 これにより、実際の関数呼び出しは、最後に呼び出されてから指定された時間が経過するまで遅延されます。 つまり、1秒の遅延(この例では効果を誇張するために使用します)と、フィールドへのクイックテキスト入力中の関数呼び出しの連続ストリームにより、実際の関数はこれから入力を停止するまで呼び出されません1秒は過ぎません。
次のような簡単なデバウンスを行いたくなるかもしれません。
var filterThrottled = _.debounce(filterAction, 1000); $scope.$watch('searchText', function(){filterThrottled($scope);});
ただし、問題があります。 このアプローチは、$ダイジェストサイクルの外側で起動するタイマーを使用するため、Angularは発生した変更を認識しないため、最終的にはUIに影響しません。 代わりに、呼び出しを$ applyでラップする必要があります 。
var filterDelayed = function($scope) { $scope.$apply(function(){filterAction($scope);}); };
その後、$ watchを設定し、入力が停止するとすぐに反応します:
var filterThrottled = _.debounce(filterDelayed, 1000); $scope.$watch('searchText', function(){filterThrottled($scope);});
もちろん、ここでの本格的な例には調整を含める必要があります。これにより、「インスタント」フィルタリングと保留の違いを確認できます。 このケースのフィドルは、 jsfiddle.net / nZdgmにあります。