《vue3的13种通信方案》

在 Vue 3 中,组件之间的通信是构建应用程序的关键。本指南将介绍 13 种不同的组件通信方法,从最简单到最复杂,帮助你选择最适合你需求的方式

1. 父组件向子组件传递数据 (Props)

「父组件:」

html 复制代码
<template>  
<child :name="name"></child>  
</template>  
  
<script setup>  
import { ref } from 'vue'  
import Child from './Child.vue'  
  
const name = ref('小明')  
</script>

「子组件:」

html 复制代码
<template>  
<div>{{ props.name }}</div>  
</template>  
  
<script setup>  
import { defineProps } from 'vue'  
  
const props = defineProps({  
    name: {  
        type: String,  
        default: '',  
        },  
    })  
</script>

2. 子组件向父组件传递数据 (Emit)

子组件可以通过触发事件的方式向父组件传递数据。 「子组件:」

html 复制代码
<template>  
<button @click="handleClick">点击我</button>  
</template>  
  
<script setup>  
import { ref, defineEmits } from 'vue'  
  
const message = ref('来自子组件的问候')  
const emits = defineEmits(['greet'])  
  
const handleClick = () => {  
emits('greet', message.value)  
}  
</script>

「父组件:」

js 复制代码
<template>  
<child @greet="handleGreet"></child>  
</template>  
  
<script setup>  
import { ref } from 'vue'  
import Child from './Child.vue'  
  
const handleGreet = (message) => {  
console.log(message) // 输出: "来自子组件的问候"  
}  
</script>

3. 兄弟组件通信 (Mitt)

对于兄弟组件之间的通信,我们可以使用第三方库 mitt 来实现一个简单的事件总线

首先,安装 mitt:

powershell 复制代码
npm install --save mitt

然后,在 main.js 中全局配置:

js 复制代码
import { createApp } from 'vue'  
import mitt from 'mitt'  
import App from './App.vue'  
  
const app = createApp(App)  
app.config.globalProperties.$bus = mitt()  
  
app.mount('#app')

「发送事件的组件:」

js 复制代码
<script setup>  
import { getCurrentInstance } from 'vue'  
  
const { proxy } = getCurrentInstance()  
const sendMessage = () => {  
proxy.$bus.emit('myEvent', '你好,兄弟')  
}  
</script>

「接收事件的组件:」

js 复制代码
<script setup>  
import { onMounted, getCurrentInstance } from 'vue'  
  
const { proxy } = getCurrentInstance()  
  
onMounted(() => {  
proxy.$bus.on('myEvent', (message) => {  
console.log(message) // 输出: "你好,兄弟"  
})  
})  
</script>

4. 透传 Attributes ($attrs)

$attrs 包含了父组件传递给子组件的所有属性,除了那些已经被 props 或 emits 声明的 「父组件:」

js 复制代码
<template>  
<child name="小明" age="18" hobby="篮球"></child>  
</template>

「子组件:」

js 复制代码
<script setup>  
import { useAttrs } from 'vue'  
  
const attrs = useAttrs()  
console.log(attrs) // { age: "18", hobby: "篮球" }  
</script>

5. 模板引用 (Refs)

通过 ref,父组件可以直接访问子组件的属性和方法。

「父组件:」

js 复制代码
<template>  
<child ref="childRef"></child>  
<button @click="callChildMethod">调用子组件方法</button>  
</template>  
  
<script setup>  
import { ref } from 'vue'  
import Child from './Child.vue'  
  
const childRef = ref(null)  
  
const callChildMethod = () => {  
childRef.value.someMethod()  
}  
</script>

「子组件:」

js「父组件:」 复制代码
<script setup>  
import { defineExpose } from 'vue'  
  
const someMethod = () => {  
console.log('子组件方法被调用了')  
}  
  
defineExpose({  
someMethod,  
})  
</script>

6. 双向绑定 (v-model)

v-model 提供了一种简洁的方式来实现父子组件之间的双向数据绑定。 「父组件:」

js 复制代码
<template>  
<child v-model:name="name"></child>  
</template>  
  
<script setup>  
import { ref } from 'vue'  
import Child from './Child.vue'  
  
const name = ref('小明')  
</script>

「子组件:」

js 复制代码
<template>  
<input :value="name" @input="updateName" />  
</template>  
  
<script setup>  
import { defineProps, defineEmits } from 'vue'  
  
const props = defineProps(['name'])  
const emit = defineEmits(['update:name'])  
  
const updateName = (e) => {  
emit('update:name', e.target.value)  
}  
</script>

7. 依赖注入 (Provide/Inject)

provide 和 inject 允许祖先组件向所有子孙组件传递数据,而不需要通过每一层组件手动传递

「祖先组件:」

js 复制代码
<script setup>  
import { provide, ref } from 'vue'  
  
const themeColor = ref('blue')  
provide('theme', themeColor)  
</script>

「子孙组件:」

js 复制代码
<script setup>  
import { inject } from 'vue'  
  
const theme = inject('theme')  
console.log(theme.value) // 'blue'  
</script>

8. 路由传参

Vue Router 提供了多种方式在路由之间传递参数。

「通过 query 传参:」

js 复制代码
import { useRouter } from 'vue-router'  
  
const router = useRouter()  
router.push({ path: '/user', query: { id: 123 } })  
  
// 在目标组件中  
import { useRoute } from 'vue-router'  
  
const route = useRoute()  
console.log(route.query.id) // 123

9. Vuex 状态管理

Vuex 是 Vue 的官方状态管理库,适用于大型应用。

js 复制代码
// store/index.js  
import { createStore } from 'vuex'  
  
export default createStore({  
    state: {  
        count: 0,  
    },  
    mutations: {  
        increment(state) {  
            state.count++  
        },  
    },  
    })  
  
// 在组件中使用  
import { useStore } from 'vuex'  
  
const store = useStore()  
console.log(store.state.count)  
store.commit('increment')

10. Pinia 状态管理

Pinia 是新一代的 Vue 状态管理库,提供更简单的 API 和更好的 TypeScript 支持。

js 复制代码
// stores/counter.js  
import { defineStore } from 'pinia'  
  
export const useCounterStore = defineStore('counter', {  
    state: () => ({ count: 0 }),  
    actions: {  
        increment() {  
            this.count++  
        },  
    },  
})  
  
// 在组件中使用  
import { useCounterStore } from '@/stores/counter'  
  
const counter = useCounterStore()  
console.log(counter.count)  
counter.increment()

11. 浏览器存储

localStorage 和 sessionStorage 可以用于在不同页面或组件之间共享数据。

js 复制代码
// 存储数据  
localStorage.setItem('user', JSON.stringify({ name: '小明', age: 18 }))  
  
// 读取数据  
const user = JSON.parse(localStorage.getItem('user'))

12. Window 对象

虽然不推荐,但在某些场景下,可以使用 window 对象在全局范围内共享数据。

js 复制代码
// 设置全局数据  
window.globalData = { message: '全局消息' }  
  
// 在任何地方使用  
console.log(window.globalData.message)

13. 全局属性

Vue 3 提供了 app.config.globalProperties 来替代 Vue 2 中的 Vue.prototype,用于添加全局可用的属性

js 复制代码
// main.js  
const app = createApp(App)  
app.config.globalProperties.$http = axios  
  
// 在组件中使用  
import { getCurrentInstance } from 'vue'  
  
const { proxy } = getCurrentInstance()  
proxy.$http.get('/api/data')

总结

这 13 种方法涵盖了 Vue 3 中几乎所有的组件通信场景。根据你的具体需求和应用规模,选择最合适的通信方式。记住,好的组件设计能够简化通信,提高代码的可维护性。

相关推荐
真滴book理喻3 分钟前
Vue(四)
前端·javascript·vue.js
蜜獾云5 分钟前
npm淘宝镜像
前端·npm·node.js
dz88i86 分钟前
修改npm镜像源
前端·npm·node.js
Jiaberrr10 分钟前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook
顾平安1 小时前
Promise/A+ 规范 - 中文版本
前端
聚名网1 小时前
域名和服务器是什么?域名和服务器是什么关系?
服务器·前端
桃园码工1 小时前
4-Gin HTML 模板渲染 --[Gin 框架入门精讲与实战案例]
前端·html·gin·模板渲染
沈剑心2 小时前
如何在鸿蒙系统上实现「沉浸式」页面?
前端·harmonyos
一棵开花的树,枝芽无限靠近你2 小时前
【PPTist】组件结构设计、主题切换
前端·笔记·学习·编辑器
m0_748237052 小时前
Chrome 关闭自动添加https
前端·chrome