前言
原先写过一篇父传子,推荐阅读:详细分析Vue3中的props用法(父传子)
实战中也常用这种方式,今天突然发现还有另外一种方式,对此进行深入探讨学习下
1. 基本知识
在 Vue 3 中,provide 和 inject 是用于组件间数据共享的 API,允许父组件向子组件传递数据而不需要通过 props 一层层传递
-
provide
:
在父组件中定义,可以提供数据给其所有子孙组件
该数据可以是任何类型(对象、数组、基本数据类型等) -
inject
:
在子组件中使用,用于接收来自祖先组件提供的数据
通过 inject,子组件可以直接使用父组件提供的数据,而无需通过 props
基本的步骤也很简单,就是父组件使用provide提供数据,子组件使用inject接收数据
2. Demo
基本的项目结构如下:
my-vue-app
├── src
│ ├── components
│ │ ├── ParentComponent.vue
│ │ ├── ChildComponent.vue
│ ├── App.vue
│ ├── main.js
创建一个父组件 ParentComponent.vue,在其中提供一些数据
<!-- src/components/ParentComponent.vue -->
<template>
<div>
<h2>父组件</h2>
<p>提供的主题颜色: {
{ themeColor }}</p>
<ChildComponent />
</div>
</template>
<script>
import {
provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
setup() {
// 创建一个响应式变量
const themeColor = ref('blue');
// 使用 provide 提供数据
provide('themeColor', themeColor);
return {
themeColor
};
}
};
</script>
- 创建子组件
创建一个子组件 ChildComponent.vue,在其中注入父组件提供的数据
<!-- src/components/ChildComponent.vue -->
<template>
<div>
<h3>子组件</h3>
<p>使用的主题颜色: {
{ themeColor }}</p>
</div>
</template>
<script>
import {
inject } from 'vue';
export default {
setup() {
// 使用 inject 获取提供的数据
const themeColor = inject('themeColor');
return {
themeColor
};
}
};
</script>
- 更新 App.vue
在 App.vue 中使用父组件:
<template>
<div id="app">
<ParentComponent />
</div>
</template>
<script>
import ParentComponent from './components/ParentComponent.vue';
export default {
components: {
ParentComponent
}
};
</script>
3. 拓展
通过按钮点击改变主题颜色
相关的结构如下:
my-vue-app
├── src
│ ├── components
│ │ ├── ParentComponent.vue
│ │ ├── ChildComponent.vue
│ │ ├── ColorChanger.vue
│ ├── App.vue
│ ├── main.js
- 在父组件 ParentComponent.vue 中提供一个状态(主题颜色)和一个方法(改变颜色):
<!-- src/components/ParentComponent.vue -->
<template>
<div>
<h2>父组件</h2>
<p>当前主题颜色: {
{ themeColor }}</p>
<ChildComponent />
<ColorChanger />
</div>
</template>
<script>
import {
provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
import ColorChanger from './ColorChanger.vue';
export default {
components: {
ChildComponent,
ColorChanger
},
setup() {
// 创建一个响应式变量
const themeColor = ref('blue');
// 方法:改变颜色
const changeColor = (newColor) => {
themeColor.value = newColor;
};
// 使用 provide 提供数据和方法
provide('themeColor', themeColor);
provide('changeColor', changeColor);
return {
themeColor
};
}
};
</script>
- 创建子组件
在子组件 ChildComponent.vue 中注入并使用主题颜色:
<!-- src/components/ChildComponent.vue -->
<template>
<div>
<h3>子组件</h3>
<p>使用的主题颜色: {
{ themeColor }}</p>
</div>
</template>
<script>
import {
inject } from 'vue';
export default {
setup() {
// 使用 inject 获取提供的数据
const themeColor = inject('themeColor');
return {
themeColor
};
}
};
</script>
- 创建颜色改变组件
在 ColorChanger.vue 中注入并使用改变颜色的方法:
<!-- src/components/ColorChanger.vue -->
<template>
<div>
<h3>颜色改变器</h3>
<button @click="changeColor('red')">红色</button>
<button @click="changeColor('green')">绿色</button>
<button @click="changeColor('blue')">蓝色</button>
</div>
</template>
<script>
import {
inject } from 'vue';
export default {
setup() {
// 使用 inject 获取提供的方法
const changeColor = inject('changeColor');
return {
changeColor
};
}
};
</script>
- 更新 App.vue
在 App.vue 中使用父组件:
<template>
<div id="app">
<ParentComponent />
</div>
</template>
<script>
import ParentComponent from './components/ParentComponent.vue';
export default {
components: {
ParentComponent
}
};
</script>
截图如下: