Я придумал очень странное поведение в Angular 1.3:
Это происходит, когда я меняю
{{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/
Я думаю, что ответ Сидхарта Панвара по большей части является правильным, кроме одного.
Объяснение: Исходным состоянием списка является ['A', 'B', 'C', 'D']
а первые 4 элемента ограничены одним ограничением (т.е. Изменение их значения не будет отражено в пользовательском интерфейсе) но в любом случае, если вход находился в диапазоне 0-3, в список добавляется новый элемент, а последний символ 'D'
в списке переносится на пятое место. Поскольку элемент на 5-м месте в списке не ограничен в один раз, в списке отображается новый D.
След:
['A', 'B', 'C', 'D']
['A','A','B', 'C'
,'D']
Так как первые 4 элемента ограничены одним ограничением, список не изменит значение, которое было связано в первом цикле дайджеста, однако, поскольку новый элемент найден на пятом месте, он должен сделать однократную привязку для этого нового элемента.
Добавление любого элемента до или в месте D в списке сдвигает последний элемент на одно место, так как этот новый элемент не связан, создается однократная привязка. Но в этом случае кажется, что новый элемент всегда будет 'D'
потому что он находится в хвосте списка.
Надеюсь это поможет!
Вот что я нашел в угловой документации:
Выражение, начинающееся с ::, считается одноразовым выражением. Одноразовые выражения останавливают пересчет, как только они стабильны.
Это фактически означает, что когда страница отображается и ng-repeat работает, итерация происходит правильно, а значения печатаются в правильном порядке. После завершения ng-repeat значение, присвоенное {{:: item}}, равно 'D'. Если изменяется длина коллекции, ng-repeat добавит новый элемент, но этот элемент будет D каждый раз, потому что {{:: item}} разрешает D. Это происходит независимо от правильной работы функции копирования и добавления правильного элемент коллекции. Итак, ваша коллекция больше не является источником истины. Это то, что одноразовое обязательство означает, что вы больше не подключены к источнику. Здесь полная дословность: почему эта функция. Основная цель одноразового обязательного выражения - предоставить способ создания привязки, которая получает отмененную регистрацию и освобождает ресурсы после стабилизации привязки. Уменьшение количества наблюдаемых выражений делает цикл дайджеста более быстрым и позволяет одновременно отображать больше информации.
Почему эта функция
Основная цель одноразового выражения привязки - предоставить способ создания привязки, которая получает отмененную регистрацию и освобождает ресурсы после стабилизации привязки. Уменьшение количества наблюдаемых выражений делает цикл дайджеста более быстрым и позволяет одновременно отображать больше информации.
Алгоритм стабилизации стоимости
Одноразовые выражения привязки сохраняют значение выражения в конце цикла дайджеста, пока это значение не определено. Если значение выражения задано в цикле дайджеста, а затем, в том же цикле дайджеста, оно установлено в undefined, тогда выражение не выполняется и останется наблюдаемым.
- Учитывая выражение, начинающееся с ::, когда вводится цикл дайджеста, и выражение грязно проверено, сохраните значение как V
- Если V не является неопределенным, отметьте результат выражения как стабильный и назначьте задачу, чтобы отменить регистрацию этого выражения, когда мы выходим из цикла дайджеста
- Обработать цикл дайджеста как обычно
- Когда цикл дайджест выполнен и все значения установлены, обработайте очередь задач дерегулирования часов. Для того, чтобы все часы были сняты с регистрации, проверьте, не оценивает ли оно все значение, которое не определено. Если это произойдет, отмените регистрацию часов. В противном случае держите грязную проверку часов в будущих циклах дайджеста, следуя тому же алгоритму, начиная с шага 1