Пытаясь управлять состояниями в 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, добавить свойство можно одним из двух способов.
- Создайте новый объект, а не добавляйте свойство.
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 может представлять некоторые трудности, но изучение того, как работать с геттерами и сеттерами, может помочь нам с легкостью создавать динамические страницы. Мы должны попытаться объявить реактивные свойства из инициализации, чтобы убедиться, что средства доступа добавлены ко всем из них, что приведет к соответствующим обновлениям страниц, отражающим изменения. Работа с данными таким образом может быть не интуитивной, но знание того, что происходит за кулисами, может помочь нам легче избежать ловушек. Удачного кодирования!