vue3之依赖注入provide(提供)/inject(注入)

时间:2024-10-13 08:17:50

通常情况下,需要从父组件传值到子组件使用props足以,但是如果是深层嵌套的组件,如果某个深层的组件想要得到祖先组件的部分数据,使用props的话需要沿着各个嵌套的组件着层传递数据,而在传递过程中的组件压根就不需要使用该数据,这些组件只是传递的一环,如果嵌套很深,这种传递数据的方式会很麻烦
通过provide(提供)/inject(注入)就能解决这个问题,父组件相对于其所有的后代组件,作为依赖的提供者,需要使用父组件数据的后代组件,无论嵌套多深都可以注入由父组件提供给整条链路的依赖,从而获取到父组件的数据

父组件提供provide(提供)

<script setup>
import {provide } from 'vue';
import inject from './components/inject.vue';
provide('key', '父组件注入的值');
</script>
<template>
  <inject />
</template>

子组件

<script setup>
import myButton from './myButton.vue'
</script>
<template>
  <myButton/>
</template>
<style>
.fancy-btn {
  color: #fff;
  background: linear-gradient(315deg, #42d392 25%, #647eff);
  border: none;
  padding: 65px 50px;
  margin: 5px;
  border-radius: 8px;
  cursor: pointer;
}
</style>

孙组件中inject(注入)
如果在注入一个值时不要求必须有提供者,那么我们应该声明一个默认值,和 props 类似

<script setup>
defineOptions({
    inheritAttrs: false
})
import {inject } from 'vue';
// const key = inject('key', 'defaultvalue'); 默认值
const key = inject('key');
</script>
<template>
<div class="btn-box">
    <button v-bind="$attrs">{{key}}</button>
</div>

</template>

在这里插入图片描述

与响应式数据配合使用及传递多个值

父组件

<script setup>
import {provide } from 'vue';
import inject from './components/inject.vue';
let prvideMsg = ref('提供者提供的数据')
function updateActiveMsg() {
  prvideMsg.value = "父组件更新提供的数据";
}
// 提供多个值的话,就用一个对象来包含所有值
provide('provideData',{
    key: '父组件注入的值',
    activeMsg: prvideMsg,
    updateActiveMsg
})
</script>
<template>
  <inject />
</template>

孙组件
当点击按钮的时候会调用祖先组件提供的更新事件

<script setup>
defineOptions({
    inheritAttrs: false
})
import {inject } from 'vue';
const {key, activeMsg, updateActiveMsg} = inject('provideData');
</script>
<template>
<div class="btn-box">
    孙组件
    <button v-bind="$attrs" @click="updateActiveMsg">{{activeMsg}}------{{key}}</button>
</div>

</template>

点击前
在这里插入图片描述
点击后
在这里插入图片描述

通过Symbol提供独一无二的注册名

新建injectedKeys文件夹用于导出注入名Symbol

export const myInjectedKey = Symbol();

依赖提供方

<script setup>
import {provide } from 'vue';
import inject from './components/inject.vue';
import {myInjectedKey } from './assets/js/privideKeys.js'
let prvideMsg = ref('提供者提供的数据')
// provide('key', '父组件注入的值');
// provide('activeMsg', prvideMsg)
function updateActiveMsg() {
  prvideMsg.value = "父组件更新提供的数据";
}
// 提供多个值的话,就用一个对象来包含所有值
provide(myInjectedKey,{
    key: '父组件注入的值',
    activeMsg: prvideMsg,
    updateActiveMsg
})
</script>

注入方组件

<script setup>
import {inject } from 'vue';
import {myInjectedKey } from '../assets/js/privideKeys.js'
const {key, activeMsg, updateActiveMsg } = inject(myInjectedKey);
</script>