当前位置: 首页 > news >正文

Vue3 provide/inject 详细组件关系说明

Vue3 provide/inject 详细组件关系说明

一、组件层级关系(家族关系)

1.1 组件结构说明

text

App.vue (爷爷组件)↓
ParentComponent.vue (爸爸组件) ↓
ChildComponent.vue (儿子组件)↓
GrandchildComponent.vue (孙子组件)

1.2 文件结构

text

src/├── App.vue                 (爷爷)├── components/│   ├── ParentComponent.vue (爸爸)│   ├── ChildComponent.vue  (儿子)│   └── GrandchildComponent.vue (孙子)

二、详细代码示例(带完整引入关系)

2.1 爷爷组件 (App.vue) - 提供数据

vue

<template><div class="app"><h2>我是爷爷组件 (App.vue)</h2><p>我提供了 userInfo 和 theme 数据</p><!-- 直接引入爸爸组件,不需要知道孙子组件的存在 --><ParentComponent /></div>
</template><script setup lang="ts">
import { ref, provide } from 'vue'
// 只需要引入直接子组件(爸爸组件)
import ParentComponent from './components/ParentComponent.vue'// 1. 准备要提供的数据
const userInfo = ref({name: '张三',age: 25,email: 'zhangsan@email.com'
})const theme = ref('dark')// 2. 提供数据给所有子孙组件(包括儿子、孙子、曾孙...)
// 这些数据可以被任何层级的后代组件获取,不需要层层传递
provide('userInfo', userInfo)
provide('theme', theme)// 在爷爷组件中也可以修改数据,所有注入的地方都会自动更新
const changeUser = () => {userInfo.value.name = '李四'userInfo.value.age = 30
}
</script>

2.2 爸爸组件 (ParentComponent.vue) - 中间层

vue

<template><div class="parent" :class="theme"><h3>我是爸爸组件</h3><p>我既不需要爷爷的数据,也不提供数据,我只是个中间人</p><!-- 引入儿子组件 --><ChildComponent /></div>
</template><script setup lang="ts">
// 爸爸组件不需要使用 provide/inject
// 它只是负责渲染儿子组件,完全不知道数据传递的事情
import ChildComponent from './ChildComponent.vue'
</script><style scoped>
.parent {padding: 20px;margin: 10px;border: 2px solid #ccc;
}
.light { background: #f5f5f5; color: #000; }
.dark { background: #333; color: #fff; }
</style>

2.3 儿子组件 (ChildComponent.vue) - 也可以注入数据

vue

<template><div class="child"><h4>我是儿子组件</h4><p>我注入了 theme:{{ theme }}</p><p>但我没有注入 userInfo,所以看不到用户信息</p><!-- 引入孙子组件 --><GrandchildComponent /></div>
</template><script setup lang="ts">
import { inject } from 'vue'
import GrandchildComponent from './GrandchildComponent.vue'// 儿子组件可以选择性地注入需要的数据
// 这里只注入了 theme,没有注入 userInfo
const theme = inject('theme')
</script><style scoped>
.child {padding: 15px;margin: 10px;border: 1px solid #666;background: #e0e0e0;
}
</style>

2.4 孙子组件 (GrandchildComponent.vue) - 注入并使用数据

vue

<template><div class="grandchild" :class="theme"><h5>我是孙子组件</h5><!-- 直接使用注入的数据 --><div class="user-card"><h3>用户信息</h3><p>姓名:{{ userInfo.name }}</p><p>年龄:{{ userInfo.age }}</p><p>邮箱:{{ userInfo.email }}</p></div><p>当前主题:{{ theme }}</p><button @click="updateUser">修改用户信息</button></div>
</template><script setup lang="ts">
import { inject } from 'vue'// 定义类型接口(TypeScript)
interface UserInfo {name: stringage: numberemail: string
}// 孙子组件注入爷爷组件提供的数据
// 注意:这里不需要引入爷爷组件!
const userInfo = inject<UserInfo>('userInfo')!
const theme = inject('theme')// 可以直接修改响应式数据(会影响到所有使用该数据的地方)
const updateUser = () => {userInfo.name = '王五'userInfo.age = 35// 这个修改会反映到所有注入了 userInfo 的组件中
}
</script><style scoped>
.grandchild {padding: 10px;margin: 10px;border: 1px dashed #999;
}
.light { background: #fff; color: #000; }
.dark { background: #222; color: #fff; }
.user-card {border: 1px solid #ccc;padding: 10px;margin: 10px 0;
}
</style>

三、关键问题解答

3.1 需要互相引入组件吗?

不需要! provide/inject 的神奇之处就在这里:

  • 爷爷组件 → 只需要引入直接子组件 (ParentComponent)

  • 孙子组件 → 完全不需要知道爷爷组件的存在

  • 数据流动:通过 Vue 的依赖注入系统,不需要显式引入

3.2 数据传递路径

text

App.vue (provide)↓ (Vue内部依赖注入系统)
GrandchildComponent.vue (inject)跳过:ParentComponent.vue 和 ChildComponent.vue

3.3 实际运行效果

在浏览器中你会看到:

text

我是爷爷组件 (App.vue)
我提供了 userInfo 和 theme 数据我是爸爸组件
我既不需要爷爷的数据,也不提供数据,我只是个中间人我是儿子组件
我注入了 theme:dark
但我没有注入 userInfo,所以看不到用户信息我是孙子组件
用户信息
姓名:张三
年龄:25
邮箱:zhangsan@email.com
当前主题:dark
[修改用户信息按钮]

四、更直观的例子:主题切换

4.1 爷爷组件提供主题切换功能

vue

<!-- App.vue -->
<template><div class="app" :class="theme"><h2>主题示例</h2><button @click="toggleTheme">切换主题</button><ParentComponent /></div>
</template><script setup lang="ts">
import { ref, provide } from 'vue'
import ParentComponent from './components/ParentComponent.vue'const theme = ref('light')// 提供主题数据
provide('theme', theme)// 提供切换主题的方法
const toggleTheme = () => {theme.value = theme.value === 'light' ? 'dark' : 'light'
}
provide('toggleTheme', toggleTheme)
</script><style>
.light { background: white; color: black; }
.dark { background: #1a1a1a; color: white; }
</style>

4.2 孙子组件使用主题功能

vue

<!-- GrandchildComponent.vue -->
<template><div class="grandchild"><p>当前主题:{{ theme }}</p><button @click="toggleTheme">在孙子组件切换主题</button></div>
</template><script setup lang="ts">
import { inject } from 'vue'const theme = inject('theme')
const toggleTheme = inject('toggleTheme') as () => void
</script>

五、总结

  1. 组件引入:只需要引入直接子组件,不需要跨层级引入

  2. 数据传递:通过 Vue 内部系统,不需要 props 层层传递

  3. 选择性注入:后代组件可以选择需要哪些数据

  4. 响应式:修改注入的数据会全局更新

  5. 类型安全:使用 TypeScript 确保类型正确

这就是 provide/inject 的强大之处——解耦组件关系,让深层嵌套的组件能直接访问需要的数据!

http://www.dtcms.com/a/461488.html

相关文章:

  • php的网站架构建设框架嘉兴网站设计
  • Redis(四)——Redis主从同步与对象模型
  • 2016年网站建设总结培训学校
  • 网站最下端怎么做动画设计培训机构
  • 用python制作相册浏览小工具
  • 字节跳动ByteDance前端考前总结
  • codex使用chrome-devtools-mcp最佳实践
  • 【Linux命令从入门到精通系列指南】export 命令详解:环境变量管理的核心利器
  • python 自动化采集 ChromeDriver 安装
  • 苏州招聘网站建设推广费
  • java8提取list中对象有相同属性值的对象或属性值
  • cuda编程笔记(26)-- 核函数使用任务队列
  • 存储芯片核心产业链研发实力:兆易创新、北京君正、澜起科技、江波龙、长电科技、佰维存储,6家龙头公司研发实力深度数据
  • 《Seq2Time: Sequential Knowledge Transfer for Video LLMTemporal Grounding》
  • 山东省建设部网站官网网站备案审核通过后
  • 浏览器兼容性问题处理
  • Day 09(下) B2a实例解说----exampleB2a.cc+ActionInitialization+PrimaryGeneratorAction
  • 分布式锁:Redisson的可重入锁
  • 计算机硬件相关(AI回答)
  • 网站设计中的用户体验大型网站需要什么样的团队
  • 淘宝网站开发方式网站托管 济南
  • 重庆网站seo案例网站推广用什么方法最好
  • sql报错:java.sql.SQLSyntaxErrorException: Unknown column ‘as0‘ in ‘where clause‘
  • 做网站是什么公司做陶瓷公司网站
  • CentOS 7上安装SonarQube8.9
  • 遗留系统微服务改造(二):数据迁移实战攻略与一致性保证
  • IO操作(Num22)
  • 领码方案|微服务与SOA的世纪对话(6):组织跃迁——智能架构下的团队与文化变革
  • 怎么什么软件可以吧做网站网站被百度收录很重要
  • C++ 单例模式(Singleton)详解