Vue.js 3.0 Tutorial

Vue.js 3.0 Component Advanced

Vue.js 3.0 Transitions & Animations

Vue.js 3.0 Reusable & Combinable

Vue.js 3.0 Advanced

Vue.js 3.0 Tools

Vue.js 3.0 Scale

Vue.js 3.0 Accessibility

Vue.js 3.0 Migrating from Vue2

Vue.js 3.0 Contribute Documentation

Vue.js 3.0 API References

Vue.js 3.0 Style Guide

Vue 3.0 provide/inject

Vue.js provides a provide and inject mechanism for dependency injection which can be quite useful in some scenarios. This is typically used to pass values from a parent component down to its descendants without having to pass props through every intermediate component.

This feature can be useful if you have deeply nested components and want to avoid passing props down multiple levels.

Here's a simple example to demonstrate provide and inject in Vue 3.0:

  • Creating a parent component with provide

In your parent component, you'll want to use the provide option to specify the data to provide to its descendant components.

<template>
  <div>
    <ChildComponent />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  provide() {
    return {
      message: 'Hello from parent'
    };
  }
};
</script>

In this example, we're providing a single value message to any child components.

  • Creating a child component with inject

In any child or grandchild components, you can use the inject option to access the provided values.

<template>
  <div>
    {{ message }}
  </div>
</template>

<script>
export default {
  inject: ['message']
};
</script>

In this example, we're injecting message from the nearest parent component that provides it. This component will now have a message property that comes from its parent component.

Note: provide and inject bindings are NOT reactive by default. If you want to make provide/inject pair reactive, make sure to provide an object and change its properties, or provide a reactive object like a ref or a reactive.

Also, remember to use this feature sparingly. It couples components together and makes the data flow in your application harder to understand since it's not as explicit as props and events. This feature is best used for providing some sort of global state or shared utilities.

  1. Vue 3.0 dependency injection with provide/inject:

    • Description: provide and inject allow a parent component to provide values down the component tree, and child components to inject those values.

    • Code:

      <!-- ParentComponent.vue -->
      <template>
        <div>
          <ChildComponent />
        </div>
      </template>
      
      <script>
      import { ref, provide } from 'vue';
      import ChildComponent from './ChildComponent.vue';
      
      export default {
        setup() {
          const data = ref('Hello from parent!');
          provide('sharedData', data);
      
          return {};
        },
        components: {
          ChildComponent,
        },
      };
      </script>
      
      <!-- ChildComponent.vue -->
      <template>
        <div>
          <p>{{ sharedData }}</p>
        </div>
      </template>
      
      <script>
      import { inject } from 'vue';
      
      export default {
        setup() {
          const sharedData = inject('sharedData');
          return { sharedData };
        },
      };
      </script>
      
  2. Vue 3.0 provide/inject for global state management:

    • Description: provide and inject can be used to create a global state management system where state is shared among different components.

    • Code:

      <!-- GlobalStateProvider.vue -->
      <template>
        <div>
          <ChildComponentA />
          <ChildComponentB />
        </div>
      </template>
      
      <script>
      import { reactive, provide } from 'vue';
      import ChildComponentA from './ChildComponentA.vue';
      import ChildComponentB from './ChildComponentB.vue';
      
      const globalState = reactive({
        message: 'Global State Message',
      });
      
      provide('globalState', globalState);
      
      export default {
        components: {
          ChildComponentA,
          ChildComponentB,
        },
      };
      </script>
      
      <!-- ChildComponentA.vue -->
      <template>
        <div>
          <p>{{ globalState.message }}</p>
        </div>
      </template>
      
      <script>
      import { inject } from 'vue';
      
      export default {
        setup() {
          const globalState = inject('globalState');
          return { globalState };
        },
      };
      </script>
      
  3. Vue 3.0 using provide/inject in composition API:

    • Description: provide and inject can be used in the composition API to share values between composition functions.

    • Code:

      <!-- CompositionAPIProvider.vue -->
      <template>
        <div>
          <ChildComponent />
        </div>
      </template>
      
      <script>
      import { ref, provide, defineComponent } from 'vue';
      import useSharedData from './useSharedData';
      
      export default defineComponent({
        setup() {
          const data = ref('Hello from composition API!');
          provide('sharedData', data);
      
          // Composition API
          const { sharedData } = useSharedData();
      
          return { sharedData };
        },
      });
      </script>
      
      // useSharedData.js
      import { inject, ref } from 'vue';
      
      export default function useSharedData() {
        const sharedData = inject('sharedData', ref('Default Value'));
      
        return { sharedData };
      }
      
  4. Vue 3.0 provide/inject and reactivity:

    • Description: provide and inject maintain reactivity. If a reactive object is provided, changes will be reactive in the injected component as well.

    • Code:

      <!-- ReactivityProvider.vue -->
      <template>
        <div>
          <ChildComponent />
        </div>
      </template>
      
      <script>
      import { reactive, provide, defineComponent } from 'vue';
      import ChildComponent from './ChildComponent.vue';
      
      export default defineComponent({
        setup() {
          const reactiveData = reactive({
            message: 'Reactive Message',
          });
      
          provide('reactiveData', reactiveData);
      
          return {};
        },
        components: {
          ChildComponent,
        },
      });
      </script>
      
      <!-- ChildComponent.vue -->
      <template>
        <div>
          <p>{{ reactiveData.message }}</p>
          <button @click="updateMessage">Update Message</button>
        </div>
      </template>
      
      <script>
      import { inject, ref } from 'vue';
      
      export default {
        setup() {
          const reactiveData = inject('reactiveData');
      
          const updateMessage = () => {
            reactiveData.message = 'Updated Message';
          };
      
          return { reactiveData, updateMessage };
        },
      };
      </script>
      
  5. Vue 3.0 provide/inject with functional components:

    • Description: provide and inject work seamlessly with functional components, allowing them to access shared values.

    • Code:

      <!-- FunctionalComponentProvider.vue -->
      <template functional>
        <ChildComponent />
      </template>
      
      <script>
      import { ref, provide } from 'vue';
      import ChildComponent from './ChildComponent.vue';
      
      export default {
        setup() {
          const data = ref('Hello from functional component!');
          provide('sharedData', data);
      
          return {};
        },
        components: {
          ChildComponent,
        },
      };
      </script>
      
      <!-- ChildComponent.vue -->
      <template functional>
        <div>
          <p>{{ inject('sharedData') }}</p>
        </div>
      </template>
      
  6. Vue 3.0 dynamic provide and inject bindings:

    • Description: provide and inject allow dynamic bindings by providing values based on certain conditions or dynamically changing contexts.

    • Code:

      <!-- DynamicBindingProvider.vue -->
      <template>
        <div>
          <ChildComponent v-if="useDynamicBinding" />
        </div>
      </template>
      
      <script>
      import { ref, provide } from 'vue';
      import ChildComponent from './ChildComponent.vue';
      
      export default {
        data() {
          return {
            useDynamicBinding: true,
          };
        },
        setup() {
          const dynamicData = ref('Dynamic Binding Data');
      
          provide('dynamicData', dynamicData);
      
          return {};
        },
        components: {
          ChildComponent,
        },
      };
      </script>
      
      <!-- ChildComponent.vue -->
      <template>
        <div>
          <p v-if="dynamicData">{{ dynamicData }}</p>
        </div>
      </template>
      
      <script>
      import { inject } from 'vue';
      
      export default {
        setup() {
          const dynamicData = inject('dynamicData');
          return { dynamicData };
        },
      };
      </script>