28.12.2017

Работа с observableArray — Knockout.js

Если вам нужно отслеживать изменения объекта и отвечать на них, то нужно использовать observable-переменные. Если же нужно отслеживать и отвечать на изменения набора данных, используйте observableArray. Это полезно во множестве случаев, где вы отображаете или редактируете множество элементов и нужны повторяющиеся участки UI, которые бы появлялись или исчезали с добавлением или удалением элементов.

Пример

var myObservableArray = ko.observableArray(); // Изначально это пустой массив
myObservableArray.push('Какое-то значение');  // Добавить значение и уведомить подписчиков

Чтобы увидеть то, как можно повесить биндинг значения observableArray в UI и дать пользователю его изменить, смотри пример простейшего списка.

Ключевой момент

observableArray смотрит за тем, какие объекты в массиве, а не состояния этих объектов

Если просто положить объект в observableArray то это не сделает все свойства этого объекта observable-переменными. Конечно, вы можете сделать эти свойства observable, если хотите, но это индивидуальный выбор. Переменная observableArray просто отслеживает какие объекты содержит, и уведомляет подписчиков, когда был добавлен или удален объект из массива.

Наполняем observableArray

Если хотите, чтобы observable массив изначально был не пустым, но содержал какие-то элементы изначально, то можно передать эти значения в виде массива в конструктор переменной. Например,

// Этот observable массив изначально содержит три объекта
var anotherObservableArray = ko.observableArray([
    { name: "Косолапый", type: "Медведь" },
    { name: "Джордж", type: "Бегемот" },
    { name: "Проворный", type: "Неизвестно" }
]);

Считывание информации из observableArray

Заглянув под капот, observableArray на самом деле является observable-переменной, где значение — это массив (плюс, observableArray добавляет некоторые дополнительные возможности, описанные ниже). Таким образом, вы можете получить лежащий во основе переменной массив из JavaScript, ссылаясь на observableArray как на функцию без параметров, как и на любую другую observable-переменную. Затем можно прочесть данные из этого обычного массива. Например,
alert('Длинна массива равна ' + myObservableArray().length);
alert('Первый элемент массива ' + myObservableArray()[0]);

С технической точки зрения, вы можете использовать любую нативную функцию JavaScript для массивов, для выполнения операций над массивом в основе переменной, но обычно есть лучшая альтернатива. observableArray в KO имеет собственные эквивалентные функции, и они более полезные, потому что:

  1. Они работают во всех целевых браузерах. (Например, нативная функция indexOfиз JavaScript не работает в IE 8 или более ранних, но функция indexOfиз KO работает везде.)
  2. Для функций, изменяющих содержимое массива, таких как push и splice, методы из KO автоматически вызывают механизмы отслеживания зависимостей, так что все подписчики будут уведомлены об изменении, и ваш UI автоматически обновится, а это говорит о значительных различиях между методами KO (например, observableArray.push(…) ) и нативными методами для массивов в JavaScript (например, observableArray().push(…)) поскольку последний не отправляет подписчикам данного массива каких-либо уведомлений об изменении содержимого.

Последующая часть страницы описывает функции observableArray для чтения и записи информации в массив.

indexOf

Функция indexOf возвращает индекс первого элемента массива, равному переданному параметру. Например, myObservableArray.indexOf(‘Blah’) вернет индекс (отсчет с нуля) первой записи в массиве, которая равна Blah, или значение -1 если совпадений не найдено.

slice

Функция slice это эквивалент для observableArray нативной JavaScript функции slice (например, она возвращает записи из вашего массива, начиная с переданного индекса начала до переданого индекса конца). Вызов myObservableArray.slice(…) эквивалентен вызову того же метода на массиве из переменной (например, myObservableArray().slice(…)).

Манипуляции с observableArray

observableArray представляет знакомый набор функций для изменения содержимого массива и уведомления подписчиков.

pop, push, shift, unshift, reverse, sort, splice

Все эти функции эквивалентны запуску нативных JavaScript функций для массива на массиве из переменной, и затем происходит уведомление подписчиков об изменении:

  • push( value ) — добавляет новый элемент в конец массива.
  • pop() — Удаляет последний элемент из массива и возвращает его.
  • unshift( value ) — Вставляет новый элемент в начало массива.
  • shift() — Удаляет первый элемент из массива и возвращает его.
  • reverse() — Обращает порядок следования элементов массива и возвращает observableArray (а не обычный массив из переменной).
  • sort() — Сортирует содержимое массива и возвращает observableArray.
    • По-умолчанию, сортировка идет в алфавитном порядке, но вы можете передать функцию, для управления тем, как должен сортироваться массив. Ваша функция должна принимать два любых объекта из массива и возвращать отрицательное значение если первый аргумент был меньше второго, положительное значение, если второй аргумент был меньше, или ноль если они эквивалентны. Например, для сортировки массива из объектов ‘person’ по фамилии, вы можете написать myObservableArray.sort(function (left, right) { return left.lastName == right.lastName ? 0 : (left.lastName < right.lastName ? -1 : 1) })
  • splice() — Удаляет и возвращает указанное количество элементов, начиная с переданного индекса. Например, myObservableArray.splice(1, 3) удалит три элемента начиная с индекса элемента 1 (то есть, 2ой, 3ий, и 4ый элемент) и вернет их в виде массива.

Для того, чтобы узнать больше о функциях для observableArray, смотри документацию на эквивалентные стандартные JavaScript функции для массивов.

replace, remove и removeAll

observableArray добавляет ещё некоторые полезные методы, которых по-умолчанию нет в JavaScript массивах:

  • replace( oldItem, newItem ) — Заменяет первое найденное значение, равное oldItem новым значением newItem.
  • remove( someItem ) — Удаляет все значения, равные someItem и возвращает их в качестве массива.
  • remove( function (item) { return item.age < 18; } ) — Удаляет все значения, чье свойство age меньше, чем 18, и вернет их в виде массива.
  • removeAll( [‘Chad’, 132, undefined] ) —Удаляет все значения равные ‘Chad’123, или undefined и вернет их в виде массива.
  • removeAll() — Удаляет все значения и вернет их в виде массива.

destroy и destroyAll

(Примечание: Обычно эти методы применяются только разработчиками на Ruby on Rails)

Функции destroy и destroyAll главным образом предназначены для удобства разработчиков на Ruby on Rails:

  • destroy( someItem ) — Найдет какие-либо объекты в массиве, которые равны someItem и установит им специальное свойство, называемое _destroy со значением true.
  • destroy( function (someItem) { return someItem.age < 18; } ) — Найдет какие-либо объекты в массиве, чье свойство age меньше, чем 18, и установит им специальное свойство, называемое _destroy со значением true.
  • destroyAll( [‘Chad’, 132, undefined] ) — Найдет какие-либо объекты в массиве, которые равны ‘Chad’123, или undefined и установит им специальное свойство, называемое _destroy со значением true.
  • destroyAll() — Установит специальное свойство _destroy со значением true всем объектам в массиве.

Итак, для чего же это свойство _destroy вообще? Оно реально интересно лишь разработчикам на Rails. В Rails есть соглашение, что когда вы передаете в действие граф JSON-объектов, фреймворк может автоматически конвертировать их в граф объектов типа ActiveRecord, и затем сохранить их в базу данных. Он знает какие из объектов уже в базе данных, и вызывает соответствующие INSERT или UPDATE выражения. Чтобы сообщить фреймворку о необходимости выполнения DELETE для записи, вы просто помечаете объект свойством _destroy равным true.

Обратите внимание, что когда KO обрабатывает биндинг foreach, он автоматически прячет любые объекты со свойством _destroy равным true. Таким образом, у вас может быть кнопка вроде “удалить” которая вызывает некоторый метод destroy(someItem) на массиве, и это незамедлительно заставляет указанный элемент исчезнуть из видимости в UI. Позже, когда вы отправите форму с графом JSON объектов в Rails, эта запись будет так же удалена из базы данных (в то время, как другие элементы массива будут вставлены или обновлены как и обычно).

Задержка и/или подавление уведомлений об изменении

Обычно, observableArray уведомляет его подписчиков мгновенно, как только изменился. Но если observableArray изменяется несколько раз или вызывает дорогие (с точки зреня производительности) обновления, то можно улучшить производительность, ограничивая или откладывая уведомления об изменении. Это достигается, используя экстендер rateLimit, например так:

// Убеждаемся, что уведомления об изменении создаются не чаще, чем раз в 50-миллисекундный период
myViewModel.myObservableArray.extend({ rateLimit: 50 });


Эксклюзивно для сайта skv1991.ru

Перепечатка и копирование строго запрещены.

Оригинал страницы

Опубликовано: 28/12/2017

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *