Реактивность и provide/inject
По умолчанию provide и inject во Vue не реактивны. Многим это не нравится. Многие хотели бы, чтобы они были реактивными. И хорошая новость в том, что добиться этого совсем несложно.
Но сначала подумайте
Описаные ниже техники нужно применять только в случае крайней необходимости. Не нужно использовать их как замену props и events.
Способ №1: с помощью поля data()
Любой объект, объявленный в поле data(), будет реактивным. Следовательно, его реактивность будет сохраняться, независимо от того, где он используется. Вы можете даже передать его в какой-то javascipt модуль за пределами вашего приложения, и любые изменения этого объекта там вызовут обновление в вашем приложении. Так что мы можем просто записать вот таким образом:
export default {
data() {
return {
reactiveObject: {
value: "Hello world"
};
}
},
provide() {
return {
reactive: this.reactiveObject
};
}
};
Способ №2: С помощью observable
Начиная с версии 2.6 во Vue доступна функция observable. Она позволяет создать реактивный объект. Собственно именно эту функцию Vue использует при добавлении реактивности к вашим данным в поле data(). Давайте перепишем предыдущий пример с использованием функции observable:
import Vue from "vue";
const reactiveObject = Vue.observable({value: "Hello world"});
export default {
provide() {
return {
reactive: reactiveObject
};
}
};
Способ №3: Использовать специальный плагин
Участник команды разработки Vue Thorsten Lünborg написал плагин, добавляющий реактивность к provide. Исходный код доступен на github. Использовать его можно двумя способами.
Как плагин
Просто подключите его в файле main.js
import Vue from 'vue';
import ReactiveProvide from 'vue-reactive-provide';
Vue.use(ReactiveProvide);
Затем используйте в любом в компоненте, из которого хотите передать данные:
export default {
reactiveProvide: {
name: 'injectedName',
include: ['reactive'],
}
data() {
return {
reactive: 'hello',
};
},
};
И в компоненте, в котором хотите получить данные:
export default {
inject: ['injectedName']
};
Как миксин
Можно использовать как миксин. Тогда не нужно регистрировать плагин глобально.
import { ReactiveProvideMixin } from 'vue-reactive-provide'
export default {
mixins: [
ReactiveProvideMixin({
name: 'injectedName',
include: ['reactive'],
})
],
data() {
return {
reactive: 'hello',
};
},
};
Когда стоит использовать описанные способы
Помните, что лучше избегать добавления реактивности к provide/inject. В большинстве случаев прекрасно работает стандартная схема обмена данными: пропсы вниз, события наверх. Она не добавляет в код лишних усложнений и сохраняет читабельность кода.