【问题标题】:Function in ng-bind , multiple call?ng-bind 中的函数,多次调用?
【发布时间】:2026-01-12 01:55:02
【问题描述】:

我无法在堆栈或谷歌上找到答案...
为什么在 ng-bind 多次调用 中起作用?

html:

<li ng-if="byProviders" ng-repeat="(key, value) in byProviderGames | groupBy: 'provider'">   
   <p ng-bind="providersNames(key)"></p>
</li>

控制器:

$scope.providersNames = function providersNames(key) {
   // providersObject's length is 8
   var index = $scope.providersObject.findIndex(function(x){ return x.name == key });

   // Call more then 1000 times
   console.log($scope.gamesProviders[index]);

   var title = $scope.providersObject[index].title;
   return title;
}

【问题讨论】:

  • 能否请您添加更多代码,是否在 ng-repeat 中?控制器是否在指令中使用?由于摘要循环的工作方式,该函数至少会被调用两次。还有其他因素,比如上面的问题。
  • @alphapilgrim 我编辑我的代码。是的,它在内部 og 一个 ng-repeat ,控制器在指令和函数中使用了 1000 次以上,但它应该被调用 8 次。
  • 是否有任何其他指令或视图使用相同的控制器?
  • @alphapilgrim ,没有
  • 我认为这与var title = $scope.providersObject[index].title; 查找有关。这个数组是在哪里形成的?是来自一些 http 响应吗?

标签: angularjs ng-bind


【解决方案1】:

ngBind source code 我们可以看到,每当ng-bind 属性使用scope.$watch 发生变化时,该指令都会注册一个ngBindWatchAction 回调来更改element.textContent

scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
  element.textContent = stringify(value);
});

watchExpression 用作scope.$watch 方法的第一个参数,在每次调用$digest() 时都会调用(至少1 次)并返回将被监视的值(但它可能会被执行多次检查模型是否未被其他观察者更改的时间)。 This is mentioned in the docs:

准备好多次调用您的 watchExpression,因为它会 如果发生更改,则在单个 $digest 循环中执行多次 检测到。

在这个例子中$scope.getName方法会被调用11次直到它的返回值稳定:

  angular.module('bindExample', [])
    .controller('ExampleController', ['$scope', function($scope) {
      $scope.name = 'Arik';   
      $scope.count = 0;
      
      $scope.getName = function() { 
        if ($scope.count < 10) { $scope.count++; } 
        console.log($scope.count);  
        return $scope.name + $scope.count; 
      };
      
    }]);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body ng-app="bindExample">
<div ng-controller="ExampleController">
  Hello <span ng-bind="getName()"></span>!
</div>
</body>

【讨论】:

    【解决方案2】:

    您可以做一些事情来帮助提高性能以及它如何影响函数被调用的次数。

    首先,您可以在 ng-repeat 的末尾添加 track by $index 语句。它最终会看起来像这样。

    ng-repeat="(key, value) in byProviderGames | groupBy: 'provider' track by $index"
    

    其次,如果只是显示数据而不会发生其他交互,您可以将它们与范围解除绑定。所以它不再脏检查更改。最终会变成这样。

    ng-repeat="(key, value) in ::byProviderGames | groupBy: 'provider'"
    

    两者兼备。

    ng-repeat="(key, value) in ::byProviderGames | groupBy: 'provider' track by $index"
    

    您甚至可以取消绑定实际值。

    <p ng-bind="::providersNames(key)"></p>
    

    我包括一个代码笔,所以你可以看到函数被调用了多少次。没有你上面说的那么多。希望能帮助到你。 CodePen

    解除绑定,由(一次性绑定)[https://docs.angularjs.org/guide/expression]

    一次性绑定 以 :: 开头的表达式被视为一次性表达式。一次性表达式一旦稳定就会停止重新计算,如果表达式结果是非未定义值,则在第一次摘要之后发生(请参阅下面的值稳定算法)。

    function exampleController($scope) {
      $scope.exampleArray = [1, 2, 3, 4];
      var exampleLookupArray = [
        { name: "Schnauzer" },
        { name: "Dachshund" },
        { name: "German Shepard" },
        { name: "Doberman Pinscher" }
      ];
      $scope.breedLookUp = function(key) {
        console.count();
        return exampleLookupArray[key-1].name;
      };
    }
    
    angular
      .module("example", [])
      .controller("exampleController", exampleController);
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
    <div class="container-fluid" ng-app="example">
      <div class="container" ng-controller="exampleController">
        <div ng-repeat="ex in ::exampleArray track by $index">
          <span ng-bind="::breedLookUp(ex)"></span>
        </div>
      </div>
    </div>

    【讨论】: