Vue 3 中的组件间通信方式
1. 父子组件通信 - Props
通过 Props,父组件可以向子组件传递数据。
<template>
<Child :username="parentData" />
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const parentData = ref('Vue Developer');
</script>
子组件接收:
<template>
<p>{{ props.username }}</p>
</template>
<script setup>
const props = defineProps({
username: {
type: String,
default: '',
},
});
</script>
2. 子父组件通信 - Emit
子组件通过触发事件将数据传递给父组件。
<script setup>
import { defineEmits } from 'vue';
const emits = defineEmits(['updateParent']);
const updateHandler = () => {
emits('updateParent', 'New Data');
};
</script>
父组件监听事件:
<template>
<Child @updateParent="handleUpdate" />
</template>
<script setup>
const handleUpdate = (data) => {
console.log(data); // 输出 "New Data"
};
</script>
3. 兄弟组件通信 - mitt.js
使用 mitt.js 实现兄弟组件之间的通信。
- 安装 mitt.js:
npm install mitt - 全局挂载:
app.config.globalProperties.$bus = new mitt();
发送事件:
import { getCurrentInstance } from 'vue';
const instance = getCurrentInstance();
instance.appContext.config.globalProperties.$bus.emit('event-name', payload);
监听事件:
import { onMounted, onUnmounted } from 'vue';
import { getCurrentInstance } from 'vue';
const instance = getCurrentInstance();
onMounted(() => {
instance.appContext.config.globalProperties.$bus.on('event-name', (payload) => {
console.log(payload);
});
});
onUnmounted(() => {
instance.appContext.config.globalProperties.$bus.off('event-name');
});
4. 非显式 Props - $attrs
$attrs 用于接收未定义为 Props 的属性。
<template>
<Child data-extra="Extra Info" />
</template>
<script setup>
import { useAttrs } from 'vue';
const attrs = useAttrs();
console.log(attrs['data-extra']); // 输出 "Extra Info"
</script>
5. 引用子组件实例 - Refs
父组件可以通过 ref 访问子组件的公开方法和属性。
<template>
<Child ref="childRef" />
<button @click="invokeChildMethod">Invoke</button>
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const childRef = ref(null);
const invokeChildMethod = () => {
childRef.value.someExposedMethod();
};
</script>
子组件暴露方法:
<script setup>
const someExposedMethod = () => {
console.log('Method Called');
};
defineExpose({ someExposedMethod });
</script>
6. 双向绑定 - v-model
v-model 提供了双向数据绑定的功能。
<template>
<Child v-model:title="pageTitle" />
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const pageTitle = ref('Page Title');
</script>
子组件实现:
<script setup>
import { defineEmits } from 'vue';
const emit = defineEmits(['update:title']);
const updateTitle = (newTitle) => {
emit('update:title', newTitle);
};
</script>
7. 多层组件通信 - Provide/Inject
Provide 和 Inject 用于跨层级的数据共享。
<script setup>
import { provide } from 'vue';
provide('sharedValue', 'Shared Data');
</script>
后代组件获取:
<script setup>
import { inject } from 'vue';
const sharedValue = inject('sharedValue');
console.log(sharedValue); // 输出 "Shared Data"
</script>
8. 路由参数通信
通过 Vue Router 传递参数。
- Query 参数:
router.push({ path: '/page', query: { key: 'value' } }); - Params 参数:
router.push({ name: 'routeName', params: { id: 1 } }); - State 参数:
router.push({ path: '/page', state: { data: 'value' } });
9. 浏览器存储 - LocalStorage/SessionStorage
利用浏览器的存储机制进行持久化或临时数据共享。
// 存储
localStorage.setItem('key', 'value');
sessionStorage.setItem('key', 'value');
// 获取
const storedValue = localStorage.getItem('key');
const sessionValue = sessionStorage.getItem('key');
// 删除
localStorage.removeItem('key');
sessionStorage.removeItem('key');
10. 全局对象挂载 - Window
通过 window 对象挂载全局变量(不推荐)。
window.globalData = 'Global Value';
console.log(window.globalData); // 输出 "Global Value"
11. 全局配置 - app.config.globalProperties
在 Vue 应用中设置全局属性。
app.config.globalProperties.$globalMsg = 'Global Message';
访问全局属性:
import { getCurrentInstance } from 'vue';
const instance = getCurrentInstance();
console.log(instance.appContext.config.globalProperties.$globalMsg);