Освободитесь от сверления Vue Prop с помощью Provide/Inject

Vue предлагает несколько способов управления потоком данных и связью между компонентами. Распространенной проблемой разработчика Vue является детализация данных, когда вы передаете данные через различные уровни компонентов, что приводит к созданию сложной и менее поддерживаемой базы кода.

Vue предлагает механизм подачи/впрыска — чистое решение для поддержки бурения. Provide/inject помогает управлять передачей данных между родительскими и глубоко вложенными дочерними компонентами.

Понимание проблемы бурения винта

Прежде чем углубляться в решение предоставления/внедрения, важно понять проблему. Детализация реквизита происходит, когда вам нужно передать данные из родительского компонента верхнего уровня в глубоко вложенный дочерний компонент.

Промежуточные компоненты в этой иерархии должны получать и передавать данные, даже если они сами их не используют. Чтобы передать данные из родительского компонента в дочерний компонент, вам нужно будет передать эти данные в качестве реквизита вашим компонентам Vue.

В качестве примера рассмотрим следующую иерархию компонентов:

Предположим, данные из компонента App должны достичь GrandChildComponent. В этом случае вам придется передать его через два промежуточных компонента, используя реквизиты, даже если этим компонентам не нужны сами данные для правильной работы. Это может привести к раздутию кода, который будет сложнее отлаживать.

Что такое предоставление/внедрение?

Vue решает эту проблему с помощью функции предоставления/внедрения, которая позволяет родительскому компоненту предоставлять данные или функции своим компонентам-потомкам, независимо от того, насколько глубоко они вложены. Это решение упрощает обмен данными и улучшает организацию кода.

Компонент поставщика

Компонент-поставщик намеревается поделиться данными или методами со своими потомками. Он использует опцию предоставления, чтобы сделать эти данные доступными для своих дочерних элементов. Вот пример компонента провайдера:

 
<template>
  <div>
    
    <ParentComponent/>
  </div>
</template>

<script setup>
import { provide } from 'vue';
import ParentComponent from './components/ParentComponent.vue';

const greeting = 'Hello from Provider';

provide('greeting', greeting);
</script>

В этом блоке кода показан компонент поставщика App, который предоставляет переменную приветствия всем своим дочерним компонентам. Чтобы предоставить переменную, вам необходимо установить ключ. Установка ключа с тем же именем, что и у переменной, помогает обеспечить удобство сопровождения вашего кода.

Компоненты-потомки

Компоненты-потомки — это компоненты внутри вложенной структуры. Они могут вставлять и использовать предоставленные данные в своем экземпляре компонента. Вот как это делается:

 <script setup>
import { inject } from 'vue';

const injectedData = inject('greeting');
</script>

Компонент-потомок внедряет предоставленные данные и может получить к ним доступ в своем шаблоне как к локально определенной переменной.

Теперь рассмотрим изображение ниже:

На этом изображении вы можете увидеть иерархию из четырех компонентов, начиная с корневого компонента, который служит отправной точкой. Остальные компоненты вложены в иерархию и заканчиваются компонентом GrandChild.

Компонент GrandChild получает данные, предоставляемые компонентом App. Используя этот механизм, вы можете избежать передачи данных через родительский и дочерний компоненты, поскольку этим компонентам не нужны данные для правильной работы.

Предоставление данных на уровне приложения (глобальном)

Вы можете предоставлять данные на уровне приложения с помощью метода Provide/Inject Vue. Это распространенный вариант использования для обмена данными и конфигурацией между различными компонентами вашего приложения Vue.

Вот пример того, как вы можете предоставить данные на уровне приложения:

 

import { createApp } from 'vue'
import App from './App.vue'

const globalConfig = {
  apiUrl: 'https://example.com/api',
  authKey: 'my-secret-key',
  
};

app.provide('globalConfig', globalConfig);

createApp(App).mount('#app')

Предположим, у вас есть приложение, которому требуется глобальный объект конфигурации, содержащий конечные точки интерфейса прикладного программирования (API), информацию для аутентификации пользователя и другие параметры.

Этого можно добиться, предоставив данные конфигурации в компоненте верхнего уровня, обычно в файле main.js, что позволит другим компонентам внедрить и использовать их:

 <template>
  <div>
    <h1>API Settings</h1>
    <p>API URL: {{ globalConfig.apiUrl }}</p>
    <p>Authentication Key: {{ globalConfig.authKey }}</p>
  </div>
</template>

<script setup>
import { inject } from 'vue';

const globalConfig = inject('globalConfig');
</script>

Вышеуказанный компонент использует функцию инъекции для доступа к объекту globalConfig, который приложение предоставляет на глобальном уровне. Вы можете получить доступ к любым свойствам или настройкам из globalConfig, интерполируя или связывая эти свойства с помощью различных методов привязки данных в Vue внутри компонента.

Преимущества и использование Provide and Inject

Вот некоторые преимущества и важные варианты использования функции предоставления/внедрения при создании веб-приложений в Vue.

Более чистый и оптимизированный по производительности код

Используя предоставление/инъекцию, вы устраняете необходимость промежуточным компонентам передавать данные, которые они не используют. В результате получается более чистый и удобный в сопровождении код за счет сокращения ненужных объявлений свойств.

Кроме того, система реактивности Vue гарантирует, что компоненты перерисовываются только при изменении их зависимостей. Предоставление/внедрение позволяет эффективно обмениваться данными, что может привести к оптимизации производительности за счет сокращения ненужных повторных рендерингов.

Улучшенная инкапсуляция компонентов

Provide/inject способствует лучшей инкапсуляции компонентов. Дочерним компонентам нужно беспокоиться только о данных, которые они явно используют, что снижает их зависимость от конкретной структуры данных родительских компонентов.

Рассмотрим компонент выбора даты, который использует локализованные настройки формата даты. Вместо того, чтобы передавать эти настройки в качестве реквизитов, вы можете предоставить их в родительском компоненте и внедрить их только в компонент выбора даты. Это приводит к более четкому разделению задач.

Внедрение зависимости

Предоставление/внедрение может служить простой формой внедрения зависимостей, делая глобальные сервисы и настройки, такие как клиенты API, конечные точки, пользовательские настройки или хранилища данных, легко доступными для любого компонента, который в них нуждается. Это обеспечивает согласованность конфигураций в вашем приложении.

Основные моменты, которые следует учитывать при использовании Provide и Inject

Хотя механизм предоставления/инжекта предлагает множество преимуществ, его следует использовать осторожно, чтобы избежать нежелательных побочных эффектов.

  • Используйте предоставление/внедрение для совместного использования важных данных или функций, необходимых в иерархии компонентов, таких как конфигурация или ключи API. Злоупотребление им может сделать отношения между компонентами слишком сложными.
  • Задокументируйте, что предоставляет компонент поставщика и какие компоненты-потомки должны внедрить. Это помогает понимать и поддерживать ваши компоненты, особенно при работе в группах.
  • Будьте осторожны при создании циклов зависимостей, когда дочерний компонент предоставляет что-то, что внедряет родительский компонент. Это приведет к ошибкам и неожиданному поведению.

Является ли Provide/Inject лучшим вариантом управления состоянием в Vue?

Provide/inject — еще одна полезная функция Vue для управления потоком данных и состоянием компонентов. У метода Provide/inject есть свои недостатки. Предоставление/внедрение может привести к проблемам при отладке, тестировании и обслуживании крупномасштабных приложений.

Использование Pinia, официальной структуры управления состоянием Vue, лучше всего подходит для обработки сложных состояний в вашем приложении Vue. Pinia обеспечивает централизованное хранилище и типобезопасный подход к управлению состоянием, что делает разработку приложений Vue более доступной.