2015-09-21 62 views
0

在我看來,我想要多次顯示計算屬性,如果我多次執行{{ctrl.Compute()}},則計算函數會被多次調用。如何在AngularJs視圖中多次顯示相同的計算值,只需調用一次計算函數

我創造了這個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> 

考慮,Y你可以看到我四次調用{{ctrl.count()}},這意味着計算髮生了四次。我如何只做一次計算並多次顯示一個值。?


請不要建議一樣,想法使控制器的陣列部分像ctrl.list,然後在視圖中使用{{ctrl.list.length}}。這個想法可能適用於這種情況,但不需要複雜的計算。

+1

將控制器'$ scope.arraylength = ctrl.count()'中的變量設置爲變量並像往常一樣顯示。然後,您可以使用監視器或特定操作調用count()函數,具體取決於您的用例... – abimelex

+0

'計算正在發生四次'不,我認爲它只是調用函數4次。我認爲'js'不會去計算它。它是從'Array'原型繼承的數組對象的屬性。糾正我,如果我錯了:)。 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length –

+0

正如我所說的這個演示'計數()'是簡單的返回數組的長度,但在真正的應用程序我想在那個函數中執行一個複雜的計算。如果從視圖中我多次調用一個函數,計算會多次發生。 –

回答

0

也許是這樣的:

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

$scope.$watch("list", function() {savedCount = ctrl.count()}); 
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的每一個變化,並調用回調函數每次。

+0

'$ scope。$ watch'是指哪個對象? –

+0

你能解釋一下你的解決方案嗎? $ watch的效率如何? –

+1

您可以使用watchCollection來提高性能,因爲您可能不需要深入觀察 – masimplo

0

您可以使用稱爲memoization的技術。

在計算中,記憶化是主要用於 通過存儲昂貴 函數調用的結果,並且當相同的輸入 再次發生返回高速緩存的結果以加速的計算機程序優化技術。

您可以使用流行的圖書館,如lodash或自己寫(不鼓勵)。

您可以找到類似於您的使用案例here的用法示例,其中討論了計算量大的過濾器,類似於使用綁定到計算函數。

+0

是的,我也在考慮使用memoization,但我確定必須有一些簡單的解決這個問題。 –

+0

我已經在很多情況下使用了它,並且發現它實現起來很簡單,與觀看者一起玩,你必須非常小心他們的表現,被解僱時,如果他們要引發連鎖反應等。 – masimplo

+0

我有一個直覺,認爲$觀察者效率不高,可能是因爲我在某處讀過它。這就是我計劃使用記憶的原因。你是否也意味着$觀察者效率低下? –

-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我怎麼能解決這個問題,你的角度版本代碼看到一個可選的解決方案。

+0

請記住,html-不安全的調用是這樣的,因爲它不安全。 – abimelex

+0

你正試圖解決這個問題,這不是我關心的問題。我想學習一個你的解決方案遠離的概念。我仍然感謝你的努力。 –