Назад к вопросам
Middle
283
questionbank
Как работает реактивность в Vue.js?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Реактивность во Vue.js основана на паттерне "наблюдатель" (Observer).
Когда создается экземпляр Vue, он проходит по всем свойствам в объекте data и преобразует их в геттеры и сеттеры с использованием Object.defineProperty в Vue 2 или Proxy в Vue 3.
Vue 2:
- При доступе к свойству (геттер) Vue отслеживает, какой компонент его использует.
- При изменении свойства (сеттер) Vue уведомляет все компоненты, которые его отслеживали, о необходимости обновления (перерисовать шаблон).
Vue 3:
- Использует
Proxyдля перехвата всех операций с объектом (добавление, удаление свойств, изменение значений и т.д.), обеспечивая более полную реактивность по сравнению с Vue 2. - Благодаря
Proxy, реактивность Vue 3 не имеет ограничений Vue 2 (не требуется$setдля добавления новых свойств).
Ключевые компоненты реактивности:
- Observer: Преобразует свойства данных в геттеры/сеттеры (Vue 2) или обрабатывает их с помощью Proxy (Vue 3).
- Dep (Dependency): Объект, ассоциированный с каждым реактивным свойством, который хранит список зависимых Watcher'ов.
- Watcher: Представляет компонент, вычисляемое свойство или watchers, которые зависят от реактивных данных. Когда данные меняются, Watcher уведомляется и запускает соответствующее действие (например, перерисовку компонента).
Пример (Vue 2):
// Внутренняя реализация (упрощенно)
function defineReactive(obj, key, val) {
let dep = new Dep(); // Создаем Dep для свойства
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
// Если есть глобальный Watcher (при отрисовке компонента)
if (Dep.target) {
dep.depend(); // Добавляем Watcher в список зависимостей Dep
}
return val;
},
set: function reactiveSetter(newVal) {
if (newVal === val) return;
val = newVal;
dep.notify(); // Уведомляем все зависимые Watcher'ы
}
});
}
// Как это выглядит в компоненте
new Vue({
data: {
message: 'Hello' // defineReactive будет применено к message
},
template: '<div>{{ message }}</div>' // При доступе к message, Watcher этого template добавится в Dep message
});