Реактивность в глубине
Время глубоко погрузиться! Ненавязчивая система реактивности Vue - одна из ее отличительных особенностей. Модели - это простые объекты JavaScript. Когда мы изменим их, представление обновится. Это делает управление состоянием простым и интуитивно понятным, однако также важно понимать, как оно работает, чтобы избежать некоторых распространенных ошибок. Мы собираемся углубиться в некоторые подробности низкоуровневой системы реактивности Вью в этом разделе.
Как отслеживаются изменения
Когда мы передаем простой объект JavaScript в экземпляр Vue в качестве параметра данных, Vue просматривает все его свойства и преобразует эти свойства в методы получения / установки, используя Object.defineProperty.
Это неослабная функция, предназначенная только для ES5, поэтому Vue не поддерживает IE8 и ниже.
Получатели / установщики невидимы для пользователей, однако, внутри они позволяют Vue выполнять отслеживание зависимостей и уведомление об изменениях при обращении к свойствам или их изменении.
Предостережение заключается в том, что браузерные консоли по-разному форматируют getter / setters при регистрации преобразованных объектов данных, поэтому мы можем захотеть установить vue-devtools для более удобного для проверки интерфейса.
Каждый экземпляр компонента всегда имеет соответствующий экземпляр наблюдателя, который записывает любые свойства, "затронутые" во время рендеринга компонента, как зависимости. Позже, когда установщик зависимости срабатывает, он уведомляет наблюдателя, что, в свою очередь, вызывает повторную визуализацию компонента.
Предупреждение об обнаружении изменений
Из-за ограничений, существующих в современном JavaScript (и отказа от Object.observe), Vue не может обнаружить добавление или удаление свойства. Поскольку Vue будет выполнять процесс преобразования получателя / установщика во время инициализации экземпляра, в объекте данных должно будет присутствовать свойство, чтобы Vue смог преобразовать его и сделать его реактивным. Например:
var vm = new Vue({
data: {
a: 1
}
})
// `vm.a` will now be reactive
vm.b = 2
// `vm.b` will NOT be reactive
Vue не позволяет нам динамически добавлять новые реактивные свойства корневого уровня в уже созданный экземпляр. Однако мы можем добавить реактивные свойства к вложенному объекту, используя метод Vue.set (object, propertyName, value):
```Vue.set(vm.someObject, 'b', 2)
Мы также можем использовать метод экземпляра vm. $ Set, это псевдоним глобального Vue.set:
this.$set(this.someObject, 'b', 2)
Иногда нам может потребоваться назначить несколько свойств существующему объекту, например, используя Object.assign () или _.extend (). Однако новые свойства, добавленные к объекту, не будут вызывать изменений. В таких случаях создайте свежий объект со свойствами как объекта mixin, так и исходного объекта:
// instead of `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
Объявление реактивных свойств
Поскольку Vue не позволяет нам динамически добавлять реактивные свойства корневого уровня, мы должны инициализировать экземпляры Vue, объявив все свойства данных корневого уровня заранее, если у свойства нет значения, используйте пустое значение:
var vm = new Vue({
data: {
// declare message with an empty value
message: ''
},
template: '<div>{{ message }}</div>'
})
// set `message` later
vm.message ='Hello!'
Неспособность объявить сообщение в параметре данных приведет к тому, что Vue предупредит нас, что функция рендеринга пытается получить доступ к несуществующему свойству.
Это исключит класс пограничных случаев в системе отслеживания зависимостей и в равной степени сделает экземпляры Vue более подходящими для систем проверки типов.
Асинхронная очередь обновлений
Обновления Vue DOM выполняются асинхронно. Когда наблюдается изменение данных, он открывает очередь и затем буферизирует все изменения данных, которые происходят в одном и том же цикле событий. В тех случаях, когда один и тот же наблюдатель запускается несколько раз, он будет помещен в очередь только один раз. Эта буферизованная дедупликация важна, чтобы избежать ненужных вычислений и манипуляций с DOM. Затем Vue сбрасывает очередь в следующем цикле событий «tick» и переходит к выполнению фактической (уже очищенной) работы. Внутренне Vue пытается использовать собственные Promise.then, setImmediate и MutationObserver для асинхронной очереди, а затем возвращается к setTimeout (fn, 0).
Например, когда мы устанавливаем vm.someData = 'new value', компонент не будет повторно визуализироваться немедленно. Это будет обновлено в следующем «тике», когда очередь очищается. Большую часть времени нам не нужно заботиться об этом, но это может быть сложно, когда мы хотим сделать что-то, что зависит от состояния DOM после обновления. Хотя Vue.js поощряет разработчиков думать «на основе данных» и избегать прямого прикосновения к DOM, бывают случаи, когда нам может потребоваться испачкать руки. Чтобы подождать, пока Vue.js не закончит обновление DOM после изменения данных, мы можем использовать Vue.nextTick (callback) сразу после изменения данных. Обратный вызов будет вызван после обновления DOM. Вот пример:
<div id="example">{{ message }}</div>
el: '#example',
data: {
message: '123'
}
})
vm.message ='new message' // change data
vm.$el.textContent ==='new message' // false
Vue.nextTick(function () {
vm.$el.textContent ==='new message' // true
})
Также существует метод экземпляра vm. $ NextTick (), это особенно удобно внутри компонентов, потому что ему не нужно глобальное Vue, и контекст this его обратных вызовов будет автоматически привязан к текущему экземпляру Vue:
`` `Vue.component ('пример', {
шаблон: '<span> {{message}} </ span>',
данные: функция () {
вернуть {
сообщение: «не обновлено»
}
},
методы: {
updateMessage: function () {
this.message = 'обновлено'
console.log (this. $ el.textContent) // => 'не обновлено'
this. $ nextTick (function () {
console.log (this. $ el.textContent) // => «обновлено»
})
}
}
})
Так как $ nextTick () вернет обещание, мы можем достичь того же, что и выше, используя новый синтаксис ES2016 async / await:
```methods: {
updateMessage: async function () {
this.message ='updated'
console.log(this.$el.textContent) // => 'not updated'
await this.$nextTick()
console.log(this.$el.textContent) // => 'updated'
}
}
Новый контент: Composer: менеджер зависимостей для PHP , R программирования