在 Angular.js 中使用 "ng-keyup" 向输入文本框添加去抖动

Adding debounce to an input text box with an "ng-keyup" in Angular.js

我有一个搜索框指令

// Define the search-box
alSH.directive('searchBox',[function(){
      return {
        restrict: 'E',
          template: `
    <input 
      placeholder="Search.." 
      class="search-box"
      ng-keyup=search($evt) 
      ng-model="query"
      ng-model-options="{ debounce: 1000 }"
    />`,
        controller: function SearchBoxController($scope, helper) {
    $scope.query = ''; //ng model
    $scope.search = function() { //this calls in every keyup event
      helper.setQuery($scope.query).search();
    };
    
    helper.setQuery('').search();
  }
    };
}]);

并且我尝试使用 ng-model-options="{ debounce: 1000 }" 但它仍然为每个击键发送网络请求而不更新 ng-model 可能是由于 ng-keyup.
我发现这个 post 要求类似的东西,但我似乎不明白解决方案

我添加了一个 codepen 演示,其中包含我试图实现此行为的上述代码片段

理想情况下,我想限制由于每次击键而发送的后端调用的数量。知道如何实现吗?

您可以使用类似的模式来完成:

var debounceTimer = false;
$scope.search= function() {
    // if there's already a timeout going, cancel the current one
    if (debounceTimer) {
        $timeout.cancel(debounceTimer);
    }
    // create a new timeout, do your thing when it ellapses
    debounceTimer = $timeout(function() { 
        // ... your action goes here, only if calls are made with at least ONE second interval ...  
        helper.setQuery($scope.query).search();        
    },
    // adjust your time interval accordingly 
    1000);
};

简答:使用 ng-change 而不是 ng-keyup

长答案:

通常使用ng-keyup是错误的,因为有很多方法可以修改输入值(例如drag-drop),而且有些键不会修改输入值,例如Esc 键。这就是为什么你应该始终小心使用 keyup 并更好地使用输入更改事件。

如果您使用 ng-model,您应该需要 ngModel 指令,注入并使用 ngModelCtrl。这就是 ng-change 为您所做的:https://github.com/angular/angular.js/blob/9bff2ce8fb170d7a33d3ad551922d7e23e9f82fc/src/ng/directive/ngChange.js

在简单的场景中,你不需要知道所有这些,你可以坚持使用 ng-change + ng-model-options,对于非常特殊的情况,当 [=31= 时有一些奇怪的 debounce/throttle/whatever 逻辑] 可能性是不够的,你写自定义例如my-change 以类似方式工作的指令。

在使用 answer provided here 进行了一些测试后,我设法添加了去抖动。
我删除了 ng-keyup=search($evt) 但保留了 ng-model-options="{ debounce: 1000 }".

    <input 
      placeholder="Search.." 
      class="search-box"
      ng-model="query"
      ng-model-options="{ debounce: 1000 }"
    />

然后在控制器中添加了一个监视程序,用于跟踪触发搜索功能的 $scope.query 变量。为了简单起见,我没有使用 newValueoldValue 的值,但如果需要,也可以使用它们来实现额外的功能。 solved codepen

          $scope.$watch('query', function (newValue, oldValue) {
            $scope.search();
          });