Пытаясь управлять состояниями в VueJS, мы можем быть удивлены, обнаружив, что на самом деле происходит под капотом, включая реактивность.

Чтобы свойство было реактивным, оно должно быть определено и инициализировано в свойстве данных или вычисляемом свойстве. Таким образом, в следующем коде через 2 секунды свойство сообщения должно быть установлено на «До свидания, мир».

Что произойдет, если мы уже инициализировали наш объект данных и хотим добавить новое свойство? Давайте посмотрим на другой пример.

Так не пойдет. Почему нет? Причина этого в том, что «количество» не определено в нашем исходном объекте myProduct. Причина этого в том, что при создании экземпляра объекта myProduct для каждого свойства добавляются геттеры и сеттеры, чтобы Vue мог отслеживать изменения и в результате запускать обновления. Когда геттеры и сеттеры определены, эти функции переопределяют поведение объектов Javascript по умолчанию. Таким образом, мы должны иметь дело с новыми свойствами по-другому.

Но как Vue это делает? В ES5 есть метод Object.defineProperty, который Vue использует для добавления средств доступа. Эта функция принимает 3 аргумента: объект, к которому добавляется свойство, имя свойства и объект, описывающий свойство (set и get). Object.defineProperty может делать и другие замечательные вещи, например делать свойства доступными только для чтения, но это не важно для того, о чем мы сейчас говорим. Давайте посмотрим на это в действии:

Object.defineProperty(myProduct, ‘name’, {
  get: function() {
    return name;
  },
  set: function(name) {
    this.name = name;
  }
});

Итак, Vue обновил наш объект myProduct, включив в него средства доступа: метод get и метод set. Добавление или удаление свойства после создания экземпляра не определяется Vue. Поскольку «количество» не определено в объекте myProduct, добавить свойство можно одним из двух способов.

  1. Создайте новый объект, а не добавляйте свойство.

2. Используйте Vue.set, чтобы убедиться, что новое свойство реактивно.

Таким образом, рекомендуется определить все наши реактивные свойства с самого начала, даже с пустым значением. Это приводит к добавлению геттеров и сеттеров к этим свойствам, а также улучшает читаемость для любых будущих разработчиков, читающих наш код.

Отметки

В Vue изменения свойств данных приводят к асинхронному повторному рендерингу DOM. Когда наблюдается изменение свойства данных, все изменения, которые происходят в том же цикле событий, будут добавлены в очередь. Если один и тот же наблюдатель (то, что проверяет изменения) запускается более одного раза, он будет помещен в очередь только один раз, чтобы избежать ненужных манипуляций с DOM. В следующем «тике» Vue очистит очередь и повторно отрендерит на основе этих изменений. Вот пример:

Массивы

Манипуляции с массивами также могут представлять некоторые проблемы, когда речь идет о реактивности в Vue.js. Такие методы, как push, включены в Vue, но обновление массивов по индексу невозможно, потому что установщики массивов не могут определить номера индексов. Поэтому, если мы хотим изменить значение в порядковом номере, мы должны использовать Vue.set:

// This array change will not be detected:
app.myArray[index] = newVal;
// This array change will be detected:
Vue.set(app.myArray, index, newVal);

Прокси в Vue.js3

Проблема обнаружения номеров индексов в массивах будет решена в следующем выпуске Vue.js. Используя прокси, мы можем устанавливать значения так же, как мы делаем это с объектами Javascript. В конце концов, массивы — это объекты с числовыми ключами!

Здесь массив имен переназначается прокси. Используя условный оператор, мы можем определить, присутствует ли нужное нам значение в этом ключе (индексе), и если это не так, мы установим его в нужное нам значение. Теперь мы можем переназначать элементы массива по индексу!

Заключение

Понимание реактивности в Vue может представлять некоторые трудности, но изучение того, как работать с геттерами и сеттерами, может помочь нам с легкостью создавать динамические страницы. Мы должны попытаться объявить реактивные свойства из инициализации, чтобы убедиться, что средства доступа добавлены ко всем из них, что приведет к соответствующим обновлениям страниц, отражающим изменения. Работа с данными таким образом может быть не интуитивной, но знание того, что происходит за кулисами, может помочь нам легче избежать ловушек. Удачного кодирования!