Vue3 provide/inject用法总结
1. 基本概念
provide/inject 是 Vue3 中实现跨层级组件通信的方案,类似于 React 的 Context。它允许父组件向其所有子孙组件注入依赖,无论层级有多深。
1.1 基本语法
// 提供方(父组件)
const value = ref('hello')
provide('key', value)// 注入方(子孙组件)
const value = inject('key')
2. 基础用法
2.1 提供静态值
<!-- Parent.vue -->
<script setup>
import { provide } from 'vue'// 提供静态值
provide('theme', 'dark')
provide('language', 'zh-CN')
</script><!-- Child.vue -->
<script setup>
import { inject } from 'vue'// 注入值
const theme = inject('theme')
const language = inject('language')
</script><template><div :class="theme"><p>Current Language: {{ language }}</p></div>
</template>
2.2 提供响应式数据
<!-- Parent.vue -->
<script setup>
import { provide, ref } from 'vue'const count = ref(0)
const updateCount = () => {count.value++
}// 提供响应式数据和更新方法
provide('count', {count,updateCount
})
</script><!-- Child.vue -->
<script setup>
import { inject } from 'vue'const { count, updateCount } = inject('count')
</script><template><div><p>Count: {{ count }}</p><button @click="updateCount">Increment</button></div>
</template>
3. 进阶用法
3.1 使用 Symbol 作为 key
// injection-keys.ts
export const COUNT_KEY = Symbol('count')
export const THEME_KEY = Symbol('theme')
<!-- Parent.vue -->
<script setup lang="ts">
import { provide } from 'vue'
import { COUNT_KEY, THEME_KEY } from './injection-keys'const count = ref(0)
provide(COUNT_KEY, count)
provide(THEME_KEY, 'dark')
</script><!-- Child.vue -->
<script setup lang="ts">
import { inject } from 'vue'
import { COUNT_KEY, THEME_KEY } from './injection-keys'const count = inject(COUNT_KEY)
const theme = inject(THEME_KEY)
</script>
3.2 提供默认值
<script setup>
import { inject } from 'vue'// 使用静态默认值
const theme = inject('theme', 'light')// 使用工厂函数作为默认值
const now = inject('timestamp', () => Date.now())
</script>
3.3 只读数据
<!-- Parent.vue -->
<script setup>
import { provide, ref, readonly } from 'vue'const count = ref(0)
// 提供只读版本,防止子组件修改
provide('count', readonly(count))// 提供更新方法
provide('updateCount', () => {count.value++
})
</script><!-- Child.vue -->
<script setup>
import { inject } from 'vue'const count = inject('count')
const updateCount = inject('updateCount')
</script>
4. 实际应用场景
4.1 主题系统
<!-- ThemeProvider.vue -->
<script setup>
import { provide, ref } from 'vue'const theme = ref('light')
const toggleTheme = () => {theme.value = theme.value === 'light' ? 'dark' : 'light'
}provide('theme', {theme,toggleTheme
})
</script><template><div :class="theme.value"><slot></slot></div>
</template><!-- 使用组件 -->
<script setup>
import { inject } from 'vue'const { theme, toggleTheme } = inject('theme')
</script><template><button @click="toggleTheme">Switch to {{ theme === 'light' ? 'dark' : 'light' }} mode</button>
</template>
4.2 多语言系统
<!-- I18nProvider.vue -->
<script setup>
import { provide, ref } from 'vue'const locale = ref('en')
const messages = {en: {greeting: 'Hello',farewell: 'Goodbye'},zh: {greeting: '你好',farewell: '再见'}
}const t = (key) => messages[locale.value][key]
const setLocale = (lang) => {locale.value = lang
}provide('i18n', {locale,t,setLocale
})
</script><!-- 使用组件 -->
<script setup>
import { inject } from 'vue'const { t, setLocale, locale } = inject('i18n')
</script><template><div><select v-model="locale"><option value="en">English</option><option value="zh">中文</option></select><p>{{ t('greeting') }}</p></div>
</template>
4.3 状态管理
<!-- Store.vue -->
<script setup>
import { provide, reactive } from 'vue'const store = reactive({user: null,todos: [],addTodo(text) {this.todos.push({ id: Date.now(), text, completed: false })},toggleTodo(id) {const todo = this.todos.find(t => t.id === id)if (todo) {todo.completed = !todo.completed}}
})provide('store', store)
</script><!-- TodoList.vue -->
<script setup>
import { inject } from 'vue'const store = inject('store')
</script><template><div><inputv-model="newTodo"@keyup.enter="store.addTodo(newTodo)"><ul><liv-for="todo in store.todos":key="todo.id"@click="store.toggleTodo(todo.id)">{{ todo.text }}</li></ul></div>
</template>
5. TypeScript 支持
5.1 类型定义
// types.ts
export interface ThemeContext {theme: Ref<'light' | 'dark'>toggleTheme: () => void
}export const ThemeSymbol = Symbol('theme')
5.2 带类型的 provide/inject
<script setup lang="ts">
import { provide, inject } from 'vue'
import { ThemeContext, ThemeSymbol } from './types'// 提供方
provide<ThemeContext>(ThemeSymbol, {theme: ref('light'),toggleTheme: () => { /* ... */ }
})// 注入方
const theme = inject<ThemeContext>(ThemeSymbol)
</script>
6. 最佳实践
-
使用 Symbol 作为 key
const MyKey = Symbol('my-key') provide(MyKey, value) -
提供只读数据
provide('data', readonly(data)) -
集中管理 injection key
// keys.ts export const THEME_KEY = Symbol('theme') export const I18N_KEY = Symbol('i18n') -
使用组合式函数封装
// useTheme.ts export function useTheme() {const theme = inject(THEME_KEY)if (!theme) {throw new Error('useTheme must be used within ThemeProvider')}return theme }
7. 注意事项
-
响应性
- 确保提供响应式数据时使用 ref 或 reactive
- 注意数据的可变性和只读性
-
默认值
- 提供合理的默认值
- 考虑使用工厂函数作为默认值
-
类型安全
- 使用 TypeScript 定义接口
- 使用 Symbol 作为 key
-
性能考虑
- 避免提供过大的数据结构
- 合理划分提供的数据范围
通过合理使用 provide/inject,我们可以有效地管理跨组件通信,构建可维护的组件树。但要注意避免过度使用,以免造成数据流向难以追踪的问题。
相关文章:
Vue3 provide/inject用法总结
1. 基本概念 provide/inject 是 Vue3 中实现跨层级组件通信的方案,类似于 React 的 Context。它允许父组件向其所有子孙组件注入依赖,无论层级有多深。 1.1 基本语法 // 提供方(父组件) const value ref(hello) provide(key, …...
Linux——网络基础(1)
文章目录 目录 文章目录 前言 一、文件传输协议 应用层 传输层 网络层 数据链路层 数据接收与解封装 主机与网卡 数据传输过程示意 二、IP和MAC地址 定义与性质 地址格式 分配方式 作用范围 可见性与可获取性 生活例子 定义 用途 特点 联系 四、TCP和UDP协…...
【记录】日常|从零散记录到博客之星Top300的成长之路
文章目录 shandianchengzi 2024 年度盘点概述写作风格简介2024年的创作内容总结 shandianchengzi 2024 年度盘点 概述 2024年及2025年至今我创作了786即84篇文章,加上这篇就是85篇。 很荣幸这次居然能够入选博客之星Top300,这个排名在我之前的所有年份…...
【二分查找】力扣373. 查找和最小的 K 对数字
给定两个以 非递减顺序排列 的整数数组 nums1 和 nums2 , 以及一个整数 k 。 定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 。 请找到和最小的 k 个数对 (u1,v1), (u2,v2) … (uk,vk) 。 示例 1: 输入: nums1 [1,7,11], nums2 …...
池化层Pooling Layer
1. 定义 池化是对特征图进行的一种压缩操作,通过在一个小的局部区域内进行汇总统计,用一个值来代表这个区域的特征信息,常用于卷积神经网络(CNN)中。 2. 作用 提取代表性信息的同时降低特征维度,具有平移…...
力扣算法题——11.盛最多水的容器
目录 💕1.题目 💕2.解析思路 本题思路总览 借助双指针探索规律 从规律到代码实现的转化 双指针的具体实现 代码整体流程 💕3.代码实现 💕4.完结 二十七步也能走完逆流河吗 💕1.题目 💕2.解析思路…...
自由学习记录(32)
文件里找到切换颜色空间 fgui中的 颜色空间是一种总体使用前的设定 颜色空间,和半透明混合产生的效果有差异,这种问题一般可以产生联系 动效就是在fgui里可以编辑好,然后在unity中也准备了对应的调用手段,可以详细的使用每一个具…...
VScode+Latex (Recipe terminated with fatal error: spawn xelatex ENOENT)
使用VSCode编辑出现Recipe terminated with fatal error: spawn xelatex ENOENT问题咋办? 很好解决,大概率的原因是因为latex没有添加到系统环境变量中,所有设置的编译工具没有办法找到才出现的这种情况。 解决方法: winR 然后输…...
「蓝桥杯题解」蜗牛(Java)
题目链接 这道题我感觉状态定义不太好想,需要一定的经验 import java.util.*; /*** 蜗牛* 状态定义:* dp[i][0]:到达(x[i],0)最小时间* dp[i][1]:到达 xi 上方的传送门最小时间*/public class Main {static Scanner in new Scanner(System.in);static f…...
PHP EOF (Heredoc) 详解
PHP EOF (Heredoc) 详解 PHP 中的 EOF(End Of File)是一种非常有用的语法特性,允许开发者创建多行字符串。它特别适合于创建格式化文本,如配置文件、HTML 模板等。本文将详细讲解 PHP EOF 的用法、优势以及注意事项。 什么是 EOF? EOF 是一种特殊的字符串定义方式,它允…...
pyautogui操控Acrobat DC pro万能PDF转Word,不丢任何PDF格式样式
为了将PDF转换脚本改为多进程异步处理,我们需要确保每个进程独立操作不同的Acrobat窗口。以下是实现步骤: 实现代码 import os import pyautogui import time import subprocess import pygetwindow as gw from multiprocessing import Pooldef conver…...
Day32:字符串的复制
在 Python 中,字符串的复制是指创建一个新的字符串,它的内容与原字符串相同。字符串是不可变的对象,这意味着你不能直接修改字符串的内容,但是可以通过复制来创建新的字符串进行操作。字符串的复制在一些情况下非常有用࿰…...
基于Mybatis继承AbstractRoutingDataSource使用自定义注解实现动态数据源
一:实现 方式一:继承AbstractRoutingDataSource使用自定义注解实现 环境:springboot3 MyBatis3 mysql-connector8 DataSourceKeyEnum枚举类 有几个数据源就配置几个枚举类,和数据源数量一一对应 class DataSourceKeyEnum{D…...
ZooKeeper 数据模型
ZooKeeper 数据模型 ZooKeeper 拥有层次化的命名空间,类似分布式文件系统,但每个节点不仅能有子节点,还可关联数据。节点路径为规范的绝对路径,用斜杠分隔,无相对引用。路径命名有如下约束: 路径名不能包…...
【VUE】Vue2中Vue.extend方法
在 Vue.js 2.x 版本中,Vue.extend() 方法被用于创建一个新的 Vue 子类,可以在该子类上扩展一些属性、指令和组件选项等,然后进行实例化。 比如,可以在创建一些类似 loading 式的函数式插件时,使用: 在 Vue…...
MaskGAE论文阅读
What’s Behind the Mask: Understanding Masked Graph Modeling for Graph Autoencoders 碎碎念:一篇论文看四天,效率也没谁了(捂脸) 看一点忘一点,虽然在本子上有记录,但还是忘,下次看一点在博客上记一点启发 本来很…...
Mybatis-plus 更新 Null 的策略踩坑记
一个bug 在一个管理页面,有一个非必填字段被设置成空了并提交更新,再次打开的时候,发现字段还在,并没有被更新成功。 使用的数据库映射框架是 Mybatis-plus ,对于Mybatis 在更新字段的时候会对空进行校验,…...
Oracle迁移DM数据库
Oracle迁移DM数据库 本文记录使用达梦官方数据迁移工具DTS,将Oracle数据库的数据迁移至达梦数据库。 1 数据准备 2 DTS工具操作步骤 2.1 创建工程 打开DTS迁移工具,点击新建工程,填写好工程信息,如图: 2.2 新建迁…...
HTML特殊符号的使用示例
目录 一、基本特殊符号的使用 1、空格符号: 2、小于号 和 大于号: 3、引号: 二、版权、注册商标符号的使用 1、版权符号:© 2、注册商标符号: 三、数学符号的使用 四、箭头符号的使用 五、货币符号的使用…...
数据结构基础之《(15)—排序算法小结》
一、排序算法的稳定性 1、稳定性是指同样大小的样本再排序之后不会改变相对次序 2、对基础类型来说,稳定性毫无意义 比如:3和3没有区别。《潜伏》里说同样两个一百元大钞,你能告诉我哪一个是高尚的那一个是龌龊的么 3、对非基础类型来说&a…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
