Реактивность и 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
. В большинстве случаев прекрасно работает стандартная схема обмена данными: пропсы вниз, события наверх. Она не добавляет в код лишних усложнений и сохраняет читабельность кода.