FRONTEND BLOG

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