爲了解決這個問題,我創建了一個名爲ngDelay的指令。
ngDelay增強了ngChange的行爲以支持所需的延遲行爲,該行爲在用戶處於非活動狀態時提供更新,而不是在每次按鍵時提供。訣竅是使用子範圍,並將ngChange的值替換爲包含超時邏輯的函數調用,並在父範圍上執行原始表達式。第二個技巧是將任何ngModel綁定移動到父範圍(如果存在)。這些更改全部在ngDelay指令的編譯階段執行。
下面是其中包含使用ngDelay一個例子的小提琴: http://jsfiddle.net/ZfrTX/7/(撰寫和編輯的我,從mainguy和Ryan Q幫助)
您可以在GitHub感謝brentvatne找到這段代碼。謝謝布倫特!
爲了便於參考,這裏的JavaScript來實現ngDelay指令:
app.directive('ngDelay', ['$timeout', function ($timeout) {
return {
restrict: 'A',
scope: true,
compile: function (element, attributes) {
var expression = attributes['ngChange'];
if (!expression)
return;
var ngModel = attributes['ngModel'];
if (ngModel) attributes['ngModel'] = '$parent.' + ngModel;
attributes['ngChange'] = '$$delay.execute()';
return {
post: function (scope, element, attributes) {
scope.$$delay = {
expression: expression,
delay: scope.$eval(attributes['ngDelay']),
execute: function() {
var state = scope.$$delay;
state.then = Date.now();
$timeout(function() {
if (Date.now() - state.then >= state.delay)
scope.$parent.$eval(expression);
}, state.delay);
}
};
}
}
}
};
}]);
如果有任何打字稿書呆子,使用打字稿從DefinitelyTyped角度定義這裏的:
components.directive('ngDelay', ['$timeout', ($timeout: ng.ITimeoutService) => {
var directive: ng.IDirective = {
restrict: 'A',
scope: true,
compile: (element: ng.IAugmentedJQuery, attributes: ng.IAttributes) => {
var expression = attributes['ngChange'];
if (!expression)
return;
var ngModel = attributes['ngModel'];
if (ngModel) attributes['ngModel'] = '$parent.' + ngModel;
attributes['ngChange'] = '$$delay.execute()';
return {
post: (scope: IDelayScope, element: ng.IAugmentedJQuery, attributes: ng.IAttributes) => {
scope.$$delay = {
expression: <string>expression,
delay: <number>scope.$eval(attributes['ngDelay']),
execute: function() {
var state = scope.$$delay;
state.then = Date.now();
$timeout(function() {
if (Date.now() - state.then >= state.delay)
scope.$parent.$eval(expression);
}, state.delay);
}
};
}
}
}
};
return directive;
}]);
interface IDelayScope extends ng.IScope {
$$delay: IDelayState;
}
interface IDelayState {
delay: number;
expression: string;
execute(): void;
then?: number;
action?: ng.IPromise<any>;
}
肯定。您可以將您已經擁有的代碼寫入指令。 – Fresheyeball
我想$ timeout.cancel(searchDelay);在你的代碼中沒用。您需要將舊搜索與新搜索進行比較以避免重複查詢。 – Alborz
如果您發現某個人能夠工作,請將答案標記爲正確。 – Doug