2015-07-01 24 views
0

我想出了在角1.3一個非常怪異的行爲:怪異的行爲角1.3時NG-重複拷貝項目

它發生時,我改變

{{item}} 

到:

{{::item}} 

並點擊「複製」按鈕;它想要做的是複製給定索引處的項目並將其放在源項目下。它所做的是複製列表中的最後一項並將其添加到列表的底部!

HTML:

<div ng-app="myApp"> 
    <div ng-controller="MyCtrl"> 
     <ul> 
      <li ng-repeat="item in items track by $index">{{::item}}</li> 
     </ul> 
     <input ng-model="newItem" type="text"></input> 
     <button ng-click="add(newItem)">Add</button> 
     <button ng-click="copy(newItem)">Copy</button> 
    </div> 
</div> 

的JavaScript:

var app = angular.module('myApp', []); 

app.controller('MyCtrl', function($scope) { 
    $scope.items = ["A", "B", "C", "D"]; 
    $scope.add = function(item) { 
     $scope.items.push(item); 
    }; 
    $scope.copy = function(item) { 
     var newItem = angular.copy($scope.items[parseInt(item)]); 
     $scope.items.splice(parseInt(item) + 1, 0, newItem); 
    };  
}); 

任何人都知道什麼是引擎蓋下回事?

這裏是一個小提琴:http://jsfiddle.net/v87kgwud/14/

+0

它如何知道索引? –

+0

如果您打開JSFiddle;因爲您可以看到該項目應該在文本框中輸入。 I.E.當您鍵入0並單擊複製時,它應複製「A」並將其放在源項目下。 –

+0

基本上,我認爲AngularJS不會在DOM中插入一個新項目,它只會在最後插入它,並更新相應的作用域。但由於文本內容不能改變(因爲一次性綁定),所以在複製之前和之後都看不到差異。我仍然在爲您尋找解決方案,以及我正在說的一些證據。 – Blackhole

回答

-1

這裏是我的角度documentation發現:
與::被認爲是一次性的表達式開始的表達式。一次性表達式一旦穩定就會停止重新計算。

這實際上意味着當頁面被渲染並且ng-repeat運行時,迭代會正確發生並且值按正確的順序打印。一旦ng-repeat結束,分配給{{:: item}}的值爲'D'。如果收集長度發生變化,ng-repeat將添加一個新項目,但該項目每次都是D,因爲{{:: item}}解析爲D.無論複製函數是否正常工作並添加了正確的元素到集合中。所以,你的收藏不再是真相的來源。這是一次性綁定的意思 - 你不再連接到源代碼。以下是完整的逐字記錄: 爲什麼使用此功能 一次性綁定表達式的主要目的是提供一種方法來創建綁定,一旦綁定穩定後就會取消註冊並釋放資源。減少正在觀看的表達式的數量使摘要循環更快,並允許同時顯示更多信息。

爲什麼這個功能

一次性綁定表達式的主要目的是提供一種方法來 創建被註銷並釋放一次 結合穩定的資源約束。減少所觀看的表達式數量 使得摘要循環更快,並允許同時顯示更多信息爲 。

值穩定算法

一次性綁定表達式,只要該值不是未定義在消化週期結束將保留表達 的值。 如果表達式的值在摘要循環中設置,並且在同一摘要循環中設置爲未定義,則 表達式不會被滿足並且將保持監視。

  1. 鑑於與::開始的表達式中,當輸入了消化環和表達是髒檢查,存儲該值爲V
  2. 如果V不是未定義,標記表達穩定的結果並計劃任務註銷手錶這個表達式時 我們退出摘要循環
  3. 過程中的消化循環正常
  4. 當消化循環完成,所有的價值觀都塵埃落定,過程的手錶註銷任務隊列中。對於每個手錶取消註冊爲 ,請檢查它是否仍然評估爲未定義的值,不是 。如果是這種情況,請註銷手錶。否則,保持 髒檢查在今後的手錶通過遵循 相同的算法,從第1步
+0

由於複製按鈕正在迭代,此解決方案不正確。我不想那樣。 –

+0

在downvoting之前,請檢查您自己的代碼。我只是在玩弄你的小提琴。無論如何,請看我更新的答案。 –

+0

我沒有downvoted你的答案的方式... –

0

開始我覺得Sidharth Panwar的回答是,除了一個在大多數情況下正確的消化循環。

說明: 列表的初始狀態是['A', 'B', 'C', 'D']和前4個元素是一個時間限定(即,在其值的變化將不會對UI反射的),但在任何情況下,如果輸入範圍是0-3,一個新元素被添加到列表中,並且列表中的最後一個字符'D'被推到第五位。由於列表中第五位的項目不是一次限定的,所以列表中將呈現一個新的D.

跟蹤

  1. 初始狀態:['A', 'B', 'C', 'D']
  2. 複製 'A' 通過給0作爲輸入到文本框
  3. 新狀態:['A','A','B', 'C','D']

由於前4個元素是一次有界的,列表不會改變在第一個摘要循環中綁定的值,但是由於在第五個元素中找到了新元素,所以必須對該新元素執行一次綁定。

在列表中D處添加任何元素會將最後一個元素移動一個位置,因爲這個新元素沒有綁定,所以會創建一個時間邊界。但在這種情況下,新元素似乎總是'D',因爲它位於列表的尾部。

希望這會有所幫助!

+0

我認爲你的解釋更有意義,但實際上對我的問題仍然沒有答案。在我的代碼中,我複製了$ scope.items [parseInt(item)]指向當時正確的項目。此外,當我填寫「X」並按下「Ädd」按鈕時,最後會添加正確的值。它爲什麼不起作用仍然是一個謎! –