为了解决这个问题,我创建了一个名为 ngDelay 的指令。
ngDelay 增强了 ngChange 的行为以支持所需的延迟行为,它在用户不活动时提供更新,而不是在每次击键时提供更新。诀窍是使用子范围,并将 ngChange 的值替换为包含超时逻辑并在父范围上执行原始表达式的函数调用。第二个技巧是将任何 ngModel 绑定移动到父范围(如果存在)。这些更改都是在 ngDelay 指令的编译阶段执行的。
这是一个包含使用 ngDelay 的示例的小提琴:
http://jsfiddle.net/ZfrTX/7/(由我编写和编辑,在 mainguy 和 Ryan Q 的帮助下)
感谢brentvatne,您可以在GitHub 上找到此代码。谢谢布伦特!
为了快速参考,这里是 ngDelay 指令的 JavaScript:
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);
}
};
}
}
}
};
}]);
如果有任何 TypeScript 专家,这里的 TypeScript 使用了来自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>;
}