Vue3入门 - provide和inject组合使用

在Vue3中,provide和inject是用于实现依赖注入的一对API。它们允许在组件树中传递和接收数据,而不需要通过每一层显式地传递props。在<script setup>语法中,provide可以用来提供一个值,而inject可以用来接收一个已经提供的值。

provide是setup函数内部的一个函数,所以不能在组件的选项对象(如data、methods、computed等)中使用provide,必须在setup函数内部调用它。

一、示例

首先在项目中创建父组件,示例如下:

TypeScript 复制代码
<template>  
  <ChildComponent />  
</template>  
  
<script setup lang="ts">  
import { provide, ref } from 'vue';  
import ChildComponent from './ChildComponent.vue';  
  
// 使用 provide 提供这个变量  
provide('message', 'Hello from Parent!');  
</script>

再创建子组件,用于接收注入的message信息,示例如下:

TypeScript 复制代码
<template>  
  <div>{{ message }}</div>  
</template>  
  
<script setup lang="ts">  
import { inject } from 'vue';  
// 使用 inject 接收提供的值  
const message = inject('message', 'Default Message'); // 第二个参数是默认值,可选  
console.log('message', message)
</script>

此时子页面中会显示父组件中provide注入的信息,如下图:

二、子组件中数据更新

在provide中不仅可以注入变量数据,也可以注入函数。所以需要在子组件中修改父级provide中数据,在父组件中通过provide再注入一个修改变量值函数即可。这里将上述示例稍作修改下,再来看看演示的结果。

父组件代码如下:

TypeScript 复制代码
<template>
  <div>
    <ChildComponent></ChildComponent>
  </div>
</template>
<script lang="ts" setup>
import ChildComponent from './ChildComponent.vue';  
import { provide, ref } from 'vue';
// 定义变量
const result = ref(0)
// 使用 provide 提供这个变量  
provide('result', result);  
// 使用 provide 提供修改变量的函数
provide('resultChange', (value: number) => result.value = value)
</script>

子组件代码如下:

TypeScript 复制代码
<template>  
  <div style="margin-bottom: 10px;">结果:{{ result }}</div>  

  <el-button @click="addEvent()">增加</el-button>
  <el-button @click="mulEvent()">减少</el-button>
</template>  
  
<script setup lang="ts">  
import { inject, ref } from 'vue';  
// 使用 inject 接收提供的值  
const result = inject('result', ref(0)); // 第二个参数是默认值,可选  
const resultChange = inject('resultChange', (value: number) => console.log(value))
// 增加
const addEvent = () => resultChange(result.value+1)
// 减少
const mulEvent = () => resultChange(result.value-1)
</script>

页面效果如下:

如果项目中已安装了并注入pinia,则可以在pinia看到provided数据了,如下图:

上述示例中,点击"增加"或"减少",页面的数值则会随之增加 或 减少了。

三、父组件中数据更新

将子组件中操作数值内容,移至父组件后,再看下效果。

父组件代码如下 :

TypeScript 复制代码
<template>
  <div>
    <ChildComponent></ChildComponent>

    <el-button @click="addEvent()">增加</el-button>
    <el-button @click="mulEvent()">减少</el-button>
  </div>
</template>
<script lang="ts" setup>
import ChildComponent from './ChildComponent.vue';  
import { provide, ref } from 'vue';

// 定义变量
const result = ref(0)
// 使用 provide 提供这个变量  
provide('result', result);  
// 增加
const addEvent = () => result.value += 1
// 减少
const mulEvent = () => result.value -= 1
</script>

子组件代码如下:

TypeScript 复制代码
<template>  
  <div style="margin-bottom: 10px;">结果:{{ result }}</div>  
</template>  
  
<script setup lang="ts">  
import { inject, ref } from 'vue';  
// 使用 inject 接收提供的值  
const result = inject('result', ref(0)); // 第二个参数是默认值,可选  
</script>

此时继续增、减操作,页面结果还是可以正常接收并更新结果。如下图:

四、setup顶层使用

这里需要注意的是,provide应该在setup中顶层使用,而不是在setup中的另一个函数中使用。

错误代码如下:

TypeScript 复制代码
<template>
  <div>
    <ChildComponent></ChildComponent>

    <el-button @click="addEvent()">增加</el-button>
    <el-button @click="mulEvent()">减少</el-button>
  </div>
</template>
<script lang="ts" setup>
import ChildComponent from './ChildComponent.vue';  
import { provide, ref } from 'vue';

// 定义变量
const result = ref(0)
// 使用 provide 提供这个变量  
// provide('result', result);  
// 增加
const addEvent = () => {
  result.value += 1
  provide('result', result)
}
// 减少
const mulEvent = () => result.value -= 1
</script>

如上写法,将provide放到函数中调用,则会报错: Vue warn: provide() can only be used inside setup();所以我们在使用provide时,应将其放在顶层定义,创建一个空的或有初始值的ref,将其传给provide函数。 然后在操作功能函数中,修改如上result变量值即可。

相关推荐
掘金酱4 小时前
社区排行榜现已上线
前端·人工智能
zzjyr4 小时前
AI 问答的流式响应是怎么实现的?从 fetch 到 SSE 逐字解析
前端·人工智能·ai编程
ikoala4 小时前
DeepSeek 官方仓库惊现 DeepSeek Harness 桌面端!
前端·javascript·后端
liangshanbo12155 小时前
React useEffect 与 useLayoutEffect 面试题整理
前端·javascript·react.js
Bs_MoneyMagnet5 小时前
基于springboot+vue的旅游景区点评系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·旅游
ID34610744205 小时前
【课程设计】基于Spring Boot+Vue的校园共享无人机服务系统设计与实现-计算机毕设 附源码44219
javascript·vue.js·spring boot·python·node.js·php·课程设计
夜不会漫长5 小时前
C++:类和对象(2)
java·javascript·c++
掰头战士5 小时前
聊聊 Function Calling,你的模型是否答非所问?
前端·typescript·agent
Yeyu5 小时前
车载多 App 同屏渲染(三):RemoteCompose 序列化 UI
前端
weixin199701080166 小时前
[特殊字符]《京东POP二手品类对接:B2C订单模型 vs 二手C2C属性的字段转换难题》(附Python源码)
前端·python·算法