Автор оригинала: Jani Hartikainen.
Эта статья объяснит лучшие практики Angularjs и объясните, почему вы должны избегать использования NG-Repeat
‘s $ index
Отказ Это было первоначально опубликовано на моем Блог Отказ
Заказчик сообщил, что они удалили элемент, и не тот элемент был удален!
Звучит как довольно серьезная ошибка. Это то, что мы получили один раз на работе. Попытка найти его довольно сложно, потому что, естественно, у клиента понятия не имели, что они сделали, чтобы воспроизвести вопрос.
Оказывается, ошибка была вызвана использованием $ index
в NG-Repeat
Отказ Давайте посмотрим на то, как это произойдет, и супер простой способ избежать этого типа ошибки, а также несколько уроков, которые мы можем извлечь из этого.
Простой список с действием
Давайте посмотрим на пример совершенно действующего NG-Repeat
и его контроллер.
- {{item.name}}
app.controller('ListCtrl', ['$scope', function($scope) { //items come from somewhere, from where doesn't matter for this example $scope.items = getItems(); $scope.remove = function(index) { var item = $scope.items[index]; removeItem(item); }; }]);
Смотри хорошо, верно? Ничего особенного особого в этом коде.
Добавление фильтра
Теперь давайте сделаем небольшое изменение: давайте добавим фильтр в список. Это достаточно общее, что нужно сделать, если у вас есть длинный список, например, чтобы позволить пользователю искать список.
Для этого примера предположим searchfilter
позволяет нам фильтровать список некоторыми поисковым запросом.
- {{item.name}}
Код контроллера остается прежним. Все еще выглядит хорошо, верно?
Там на самом деле сейчас ошибка. Можете ли вы найти это? Вы бы подумали об этом, если бы я не упомянул об этом?
Использование $ индекс следует избегать
Ошибка находится в контроллере:
$scope.remove = function(index) { var item = $scope.items[index]; removeItem(item); };
Поскольку мы используем здесь индекс, мы столкнемся к проблемам, как только мы отфильтровали список таким образом, что приводит к тому, что индексы не соответствуют исходному списку.
К счастью, есть действительно простой способ избежать этого: вместо использования $ index
предпочитаю пройти фактические объекты вокруг.
- {{item.name}}
$scope.remove = function(item) { removeItem(item); };
Обратите внимание, как я изменил Удалить ($ index)
в Удалить (элемент)
и изменил $ Scope.remove
Функция для работы непосредственно на объекте вместо этого.
Это простые изменения полностью избегают ошибки.
Чтобы лучше проиллюстрировать проблему и решение, вы можете использовать этот Интерактивный пример Отказ
Что мы можем извлечь из этого?
Первый урок, конечно, мы должны быть осторожны при использовании $ index
, как это может легко вызвать ошибки при использовании определенными способами.
Второй урок заключается в том, что, признавая подобные шаблоны, вы можете установить лучшие способы выполнения вещей, которые могут полностью избежать определенных типов ошибок. Я определенно рекомендую всем, чтобы избежать $ index
Сейчас и в результате их код будет иметь меньше ошибок только из этой простой смены мышления.
Третий урок – это тесты, не всегда помогут вам. Даже если у вас есть автоматические тесты, охватывающие что-то вроде этого, их довольно легко пропустить это, потому что ошибки, вызванные этой, зависят так много на определенных данных. Ошибка не всегда будет проявляться, даже при использовании фильтрации.
Четвертый урок не нарушает абстракцию – этот очень легко пропустить. Технически $ index
создан «шаблон переменной» NG-Repeat
Отказ Это только точна и имеет значение внутри повторяющегося блока. Когда мы проходим значение, он теряет свой контекст, и он больше не действителен. Для того, чтобы он был действителен за пределы повторения, мы также должны были бы фильтровать список в нашем контроллере, что потребует некоторого дублирования кода, которое следует избегать. К счастью, шаблон, представленный в этой статье, может быть использован, чтобы избежать этого.