如何通过仅调用一次compute函数在AngularJs视图中多次显示相同的计算值

时间:2015-09-21 09:55:38

标签: angularjs angularjs-view

在我看来,我想多次显示一个计算属性,如果我多次执行{{ctrl.Compute()}},那么计算函数会被多次调用。

我创建了这个plunkr演示,只是我的问题 http://plnkr.co/edit/TcMcJUipLKk94dthnivU

控制器

app.controller('MainController',function(){
  var ctrl= this;
  var list = [];

  ctrl.count = function(){
    console.log('Invoked');
    return list.length
  }


  ctrl.add = function(){
    list.push(1)
  }

});

查看

 <body ng-controller="MainController as ctrl">
    <button ng-click="ctrl.add()">Add</button>
    <br>
    List Size: {{ctrl.count()}} <br>
    List Size: {{ctrl.count()}} <br>
    List Size: {{ctrl.count()}} <br>
    List Size: {{ctrl.count()}} <br>
  </body>

在视图中,您可以看到我正在调用{{ctrl.count()}}四次,这意味着计算发生了四次。如何只进行一次计算并多次显示一个值。?

请不要建议像#{1}}那样构建控件的数组,然后在视图中使用ctrl.list。这个想法可能就此而言,但不适用于需要复杂计算的地方。

4 个答案:

答案 0 :(得分:0)

也许是这样的:

var savedCount = ctrl.count();
ctrl.count = function(){
    console.log('Invoked');
    return list.length
}

$scope.$watch("list", function() {savedCount = ctrl.count()});

答案 1 :(得分:0)

检查Plunker。在范围上使用新变量,如:

ctrl.counter = ctrl.count();
$scope.$watch(function () {
  return list;
}, function () {
  ctrl.counter = ctrl.count();
}, true);

在HTML上:

List Size: {{ctrl.counter}} <br>
List Size: {{ctrl.counter}} <br>
List Size: {{ctrl.counter}} <br>
List Size: {{ctrl.counter}} <br>

$watch function 观看list的每次更改,并且每次都调用回调函数。

答案 2 :(得分:0)

您可以使用称为memoization的技术。

  

在计算中,memoization是一种主要使用的优化技术   通过存储昂贵的结果来加速计算机程序   函数调用并在相同输入时返回缓存结果   再次发生。

您可以使用像lodash这样的热门图书馆,也可以自己编写(不鼓励)。

您可以找到与您的用例here类似的用法示例,其中讨论计算量较大的过滤器,类似于使用绑定到计算函数。

答案 3 :(得分:-1)

你可以使用bindHtmlUnsafe指令来完成它,并且你的count对象应该是$ scope对象,那么它是可能的。请复制粘贴我的答案。

    app.controller('MainController',function($scope){
     $scope.list = [];  

      $scope.context = '<br/> List Size: ' +
       $scope.list.length + ' <br/>List Size: ' + $scope.list.length + 
      '<br/>List Size: ' + $scope.list.length + ' <br/> List Size: ' + 
        $scope.list.length + ' <br/>';

     $scope.add = function () {
        $scope.list.push(1);
        $scope.context = '<br/> List Size: ' + $scope.list.length + ' <br/>List  
        Size: ' + $scope.list.length + '<br/>List Size: ' + $scope.list.length + 
       '<br/> List Size: ' + $scope.list.length + ' <br/>';
    }    
  });

app.directive('bindHtmlUnsafe', function ($compile) {
    return function ($scope, $element, $attrs) {

        var compile = function (newHTML) { // Create re-useable compile function
            newHTML = $compile(newHTML)($scope); // Compile html
            $element.html('').append(newHTML); // Clear and append it
        };

        var htmlName = $attrs.bindHtmlUnsafe; // Get the name of the variable 
        // Where the HTML is stored

        $scope.$watch(htmlName, function (newHTML) { // Watch for changes to 
            // the HTML
            if (!newHTML) return;
            compile(newHTML);   // Compile it
        });

    };
});

然后

<body ng-controller="MainController">
      <button ng-click="add()">Add</button>
            <div bind-html-unsafe="context"></div>
  </body>

这是您的问题的一个可选解决方案:)

请参阅Plunker如何使用角度版本代码解决此问题。