Javascript 我可以对手表进行去盎司或节流吗<;输入>;在AngularJS中使用lodash?
我有以下代码,它在绑定到$scope.id的Javascript 我可以对手表进行去盎司或节流吗<;输入>;在AngularJS中使用lodash?,javascript,angularjs,lodash,Javascript,Angularjs,Lodash,我有以下代码,它在绑定到$scope.id的字段上进行监视。每次输入字段值更改时,都会执行watch函数: $scope.$watch("id", function (id) { // code that does something based on $scope.id }); 有没有一种方法我可以在这个上面加一个超时或者用_lodash去抖动这个,这样代码 当用户更改值时,不会在每次按键时执行 我想要的是一个 延迟一秒钟,以便在用户停止键入一秒钟后 手表内的代码块将运行。请注意,
字段上进行监视。每次输入字段值更改时,都会执行watch函数:
$scope.$watch("id", function (id) {
// code that does something based on $scope.id
});
有没有一种方法我可以在这个上面加一个超时或者用_lodash去抖动这个,这样代码
当用户更改值时,不会在每次按键时执行
我想要的是一个
延迟一秒钟,以便在用户停止键入一秒钟后
手表内的代码块将运行。请注意,输入值是可以随时更改的。例如,如果值为“1”或“10”或“1000”,则需要调用该函数。这类似于谷歌搜索框的工作方式。如果用户键入999,则需要调用该函数。如果他删除了一个9,所以是99,那么我需要调用这个函数
我确实有可用的lodash,因此使用它的解决方案可能最适合我的需要 这就是你要找的吗
$scope.$watch("id", _.debounce(function (id) {
// Code that does something based on $scope.id
// This code will be invoked after 1 second from the last time 'id' has changed.
}, 1000));
但是,请注意,如果要在该函数中更改$scope,则应将其包装为$scope。$apply(…)
,除非\uoBounce
函数在内部使用$timeout
(据我所知,它没有这样做),Angular将不会知道您对$scope
所做的更改
更新
至于更新的问题-是的,您需要用
$scope.$apply()
:
您可以将其封装在指令中。资料来源:
您可以在Angular 1.3.0中使用ngModelOptions HTML:
姓名:
清除
user.name=
更多信息:我知道这个问题需要一个lodash解决方案。无论如何,这里有一个角度唯一的解决方案:
app.controller('BlaCtrl', function(debounce) {
$scope.$watch("id", debounce(function (id) {
....
}, 1000));
});
在控制器中:
瓦伊达-是的,我认为这是需要的,但我不确定我应该使用去盎司还是油门?我试图寻找一些例子,但没有太多。你认为节流阀在这里会实现什么?可以用电梯类比来描述
debounce
和throttle
之间的区别。如果有几个人进入电梯,除非有足够的时间关门,否则电梯不会运行——这是“去盎司”。如果电梯很小,有太多的人想进入,它最终必须运行(比如说最多有5人)-这是“油门”,我更新了问题,以显示你的建议。我应该将所有内容都包装在$scope.$apply()中,还是可以在代码末尾和函数中运行$scope.$apply()?因此,如果您想在用户键入时永远等待,请使用debounce'。如果您希望在最大延迟后执行操作,即使用户没有停止键入-使用
throttle`我已经更新了答案-是的,最好用$apply包装代码。这是推荐的方法。只有在代码块中没有抛出异常并且实际调用了$apply()时,最后调用$apply()才有效。在这方面,用$apply()包装代码是安全的-Angualar将知道代码中发生了什么。如果您能够使用Angular 1.3,这绝对是一种方法!但是,它不应该更像var args=arguments;timeout=$timeout(函数(){callback.apply(this,args);},interval)代码>?id参数将无法用您的代码定义,并且将完全丢失。是的,您是对的,谢谢。在简单的监视中,您可以只从范围中获取值,但当然最好将参数传递给回调。
<input type="text" ng-model="id" ng-debounce="1000">
app.directive('ngDebounce', function ($timeout) {
return {
restrict: 'A',
require: 'ngModel',
priority: 99,
link: function (scope, elm, attr, ngModelCtrl) {
if (attr.type === 'radio' || attr.type === 'checkbox') {
return;
}
var delay = parseInt(attr.ngDebounce, 10);
if (isNaN(delay)) {
delay = 1000;
}
elm.unbind('input');
var debounce;
elm.bind('input', function () {
$timeout.cancel(debounce);
debounce = $timeout(function () {
scope.$apply(function () {
ngModelCtrl.$setViewValue(elm.val());
});
}, delay);
});
elm.bind('blur', function () {
scope.$apply(function () {
ngModelCtrl.$setViewValue(elm.val());
});
});
}
};
});
<div ng-controller="Ctrl">
<form name="userForm">
Name:
<input type="text" name="userName"
ng-model="user.name"
ng-model-options="{ debounce: 1000 }" />
<button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button><br />
</form>
<pre>user.name = <span ng-bind="user.name"></span></pre>
</div>
app.factory('debounce', function($timeout) {
return function(callback, interval) {
var timeout = null;
return function() {
$timeout.cancel(timeout);
var args = arguments;
timeout = $timeout(function () {
callback.apply(this, args);
}, interval);
};
};
});
app.controller('BlaCtrl', function(debounce) {
$scope.$watch("id", debounce(function (id) {
....
}, 1000));
});