Vue3组件通信终极指南:十二种武器
本文最后更新于 46 天前,其中的信息可能已经有所发展或是发生改变。

企业级解决方案|完整代码示例|最佳实践指南


📦 核心通信模式

1. Props/Events 基础通信

<!-- Parent.vue -->
<template>
  <Child :message="msg" @update="handleUpdate"/>
</template>

<!-- Child.vue -->
<script setup>
defineProps({ message: String })
const emit = defineEmits(['update'])
emit('update', 'new value')
</script>

🔔 适用场景:父子组件简单数据传递


2. 增强型 v-model

<!-- Parent.vue -->
<UserForm v-model:name="form.name"/>

<!-- UserForm.vue -->
<script setup>
defineProps(['name'])
defineEmits(['update:name'])
</script>

🌟 优势:支持多个双向绑定参数


3. 模板引用

<template>
  <VideoPlayer ref="player"/>
</template>

<script setup>
const player = ref()
// 调用子组件暴露的方法
player.value.play() 

// 子组件暴露方法
defineExpose({ 
  play: () => {
    /* 播放逻辑 */
  } 
})
</script>

⚠️ 注意:避免过度依赖组件实例方法


🌐 全局通信方案

4. 依赖注入

// 祖先组件
<script setup>
const theme = reactive({ color: 'blue' })
provide('theme', readonly(theme))
</script>

// 后代组件
<script setup>
const theme = inject('theme')
</script>

🔧 最佳实践:使用 readonly 防止意外修改


5. Pinia 状态管理

// stores/counter.ts
export const useCounter = defineStore('counter', () => {
  const count = ref(0)
  const increment = () => count.value++
  return { count, increment }
})

// 组件使用
<script setup>
const counter = useCounter()
counter.increment()
</script>

📊 数据流:适合中大型应用状态管理


6. 事件总线

// utils/event.ts
import mitt from 'mitt'
export const emitter = mitt()

// 组件A
emitter.emit('toast', '操作成功')

// 组件B
emitter.on('toast', msg => console.log(msg))

🚨 注意:需在组件卸载时移除监听


🛠️ 高级模式

7. 属性透传

<template>
  <BaseInput v-bind="$attrs"/>
</template>

<script setup>
// 底层组件
defineProps(['modelValue'])
</script>

💡 技巧:配合 inheritAttrs: false 使用


8. 作用域插槽

<!-- 使用 -->
<DataTable #row="{ item }">
  <td>{{ item.name }}</td>
</DataTable>

<!-- 实现 -->
<tr v-for="item in items">
  <slot name="row" :item="item"/>
</tr>

🎨 适用场景:高度可定制的UI组件


🔗 路由与存储

9. 路由参数

<script setup>
const route = useRoute()
const id = computed(() => route.params.id)
router.push({ name: 'user', params: { id: 1 } })
</script>

🌐 最佳实践:使用路由守卫管理参数验证


10. 组合式函数

// utils/useMouse.ts
export function useMouse() {
  const x = ref(0)
  onMounted(() => 
    window.addEventListener('mousemove', e => x.value = e.x)
  )
  return { x }
}

// 使用
const { x } = useMouse()

🧩 优势:逻辑复用与解耦


11. Web存储

// utils/storage.ts
export function useSyncStorage(key: string, value: any) {
  const data = ref(JSON.parse(localStorage.getItem(key)) || value)
  watch(data, val => 
    localStorage.setItem(key, JSON.stringify(val))
  )
  return data
}

// 使用
const settings = useSyncStorage('settings', { theme: 'light' })

🔐 安全增强:建议添加数据加密


📋 方案选型表

场景 推荐方案 代码示例 优势
父子组件通信 Props/Events defineProps + defineEmits 简单直接
跨层级状态共享 Provide/Inject provide + inject 解决嵌套传递问题
全局状态管理 Pinia defineStore + useStore 类型安全/可维护性
组件方法调用 模板引用 ref.value.method() 直接访问实例
非父子组件通信 事件总线 emitter.emit/on 灵活解耦
页面状态持久化 路由参数 route.params URL可分享

🚀 企业级实践

// 严格类型约束
defineProps<{
  id: number
  items: Array<{ name: string }>
}>()

// 安全事件总线
type Events = {
  login: { userId: number }
  error: string
}
const emitter = mitt<Events>()

// 防抖函数
export function useDebounce(fn: Function, delay: number) {
  let timer: number
  return (...args: any[]) => {
    clearTimeout(timer)
    timer = setTimeout(() => fn(...args), delay)
  }
}

📚 扩展阅读推荐

▶️ ‌Vue3组件基础
▶️ Vue3 Provide/Inject API
▶️ ‌‌Pinia 官方文档‌
▶️ ‌Mitt GitHub 仓库
▶️‌ Vue3 组合式API指南
▶️ 使用Vue3和Composition API管理Web存储‌

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇