mitt在vue3中的多种使用方式

使用方式1

安装mitt

pnpm

pnpm i mitt

npm

npm i mitt

yarn

yarn add mitt 

在main.ts文件中导入mitt

import mitt from "mitt";

//...
const app = createApp(App);
app.config.globalProperties.Bus = mitt();
app.mount("#app");

在.vue文件中使用

<script setup lang="ts">
import {ComponentInternalInstance} from "vue";
const {Bus} = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties;
    
const emitEvent = () => {
    Bus.emit("eventName"); // 触发的事件名称
}
</script>

<template>
  <button @click="emitEvent">触发事件</button>
</template>

<script setup lang="ts">
import {ComponentInternalInstance} from "vue";
const {Bus} = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties;
    
// 触发的事件名称
Bus.on("eventName",() => {
    // 做些什么
}); 

</script>
<think>我们被要求回答关于Vue3组件通信的多种方式。根据提供的引用,我们可以总结出以下通信方式: 1. 父组件向子组件传递数据(Props):父组件通过属性向子组件传递数据。 2. 子组件向父组件传递数据(Emit):子组件通过触发事件向父组件传递数据。 3. 透传Attributes($attrs):用于父组件向子组件传递未在子组件props中声明的属性。 4. 使用$parent和$children(在Vue3中有所变化,可以使用getCurrentInstance()来获取父组件实例)或者通过defineExpose暴露子组件的属性或方法,然后父组件通过ref来访问。 5. 事件总线(Event Bus):在Vue3中,官方推荐使用mitt等第三方库来实现事件总线,因为Vue3移除了$on, $off等方法。 6. 使用全局状态管理(如Vuex或Pinia)进行跨组件通信。 7. 使用provide/inject实现祖先组件和后代组件之间的通信。 注意:引用中提到了13种方法,但具体内容没有全部给出。我们可以结合常见的方式补充完整。 根据Vue3的常见通信方式,我们可以列举如下(尽量达到13种): 1. Props 2. Emit / Events 3. v-model (在Vue3中,v-model是props和emit的语法糖,可以算作一种) 4. ref 和 defineExpose(父组件通过ref获取子组件实例并调用其方法或访问数据) 5. $attrs(包含父作用域中不作为组件props或自定义事件的attribute绑定和事件) 6. provide / inject 7. Event Bus(事件总线,使用第三方库) 8. Vuex 9. Pinia(Vue3推荐的状态管理库) 10. 使用全局属性(app.config.globalProperties)来挂载全局方法或属性 11. 使用模板引用(直接在模板上使用ref属性,然后在父组件中操作子组件) 12. 使用插槽(Slot)作用域插槽可以实现子组件向父组件传递数据) 13. 使用本地存储(如localStorage、sessionStorage)进行通信(虽然不响应式,但可以作为一种通信方式) 但是,注意引用中提到的13种方法可能包括了一些变体。我们结合引用内容进行整理: 引用[1]:Props和Emit。 引用[2]:事件总线(Event Bus)和透传Attributes($attrs)。 引用[3]:使用$parent(在Vue3中,通过getCurrentInstance获取)和defineExpose。 引用[4]:提到了v-model和事件绑定(但问题部分没有直接回答,我们可以补充)。 引用[5]:再次提到了Props和子组件向父组件传递数据(Emit)。 因此,我们按照13种方法进行总结(如果不够13种,可以适当补充),并给出简单示例: 1. Props:父组件向子组件传递数据(如上引用示例) 2. Emit:子组件向父组件传递数据(子组件触发事件,父组件监听) 3. v-model:在Vue3中,一个组件可以有多个v-model绑定,例如:<Child v-model:title="pageTitle" v-model:content="pageContent" /> 4. ref 和 defineExpose:子组件使用defineExpose暴露数据或方法,父组件通过ref获取子组件实例并调用。 5. $attrs:包含父组件传递的未在子组件props中声明的属性和事件。子组件可以通过v-bind="$attrs"传递给内部元素。 6. 插槽(Slot):默认插槽、具名插槽。作用域插槽允许子组件向父组件传递数据(父组件在插槽内容中使用子组件的数据)。 7. provide / inject:祖先组件提供数据,后代组件注入数据(可以是响应式数据)。 8. 事件总线(Event Bus):使用第三方库(如mitt)创建事件中心,实现跨组件通信。 9. Vuex:集中式状态管理,适用于中大型应用。 10. Pinia:新一代状态管理库,与Vue3更契合。 11. 全局属性(globalProperties):通过app.config.globalProperties挂载全局方法或属性,组件内通过getCurrentInstance()?.proxy访问。 12. $parent 和 $children(在Vue3中,官方不推荐直接使用,但可以通过getCurrentInstance()获取父组件实例,注意谨慎使用) 13. 使用浏览器存储(localStorage, sessionStorage)配合事件监听(如storage事件)实现跨标签页通信,也可以作为组件通信的补充。 下面我们按照这个顺序进行详细说明,并给出部分代码示例(由于引用中已有部分示例,我们将重复的简化,重点给出Vue3的组合式API写法): </think>### Vue3组件通信的多种方式 以下是Vue3中13种组件通信方式的详细说明及代码示例: 1. **Props(父传子)** 父组件通过属性向子组件传递数据: ```vue <!-- 父组件 --> <Child :title="pageTitle" /> <script setup> import { ref } from &#39;vue&#39; const pageTitle = ref(&#39;首页&#39;) </script> ``` ```vue <!-- 子组件 --> <script setup> defineProps({ title: { type: String, required: true } }) </script> ``` 2. **Emit(子传父)** 子组件通过事件向父组件传递数据: ```vue <!-- 子组件 --> <button @click="$emit(&#39;update&#39;, newValue)">提交</button> <script setup> const emit = defineEmits([&#39;update&#39;]) </script> ``` ```vue <!-- 父组件 --> <Child @update="handleUpdate" /> ``` 3. **v-model(双向绑定)** 语法糖实现父子组件双向绑定: ```vue <!-- 父组件 --> <Child v-model:count="num" /> ``` ```vue <!-- 子组件 --> <input :value="count" @input="$emit(&#39;update:count&#39;, $event.target.value)"> <script setup> defineProps([&#39;count&#39;]) defineEmits([&#39;update:count&#39;]) </script> ``` 4. **透传 Attributes($attrs)** 传递未声明的props: ```vue <!-- 父组件 --> <Child data-id="123" class="active" /> ``` ```vue <!-- 子组件 --> <div v-bind="$attrs">接收透传属性</div> ``` 5. **Ref / defineExpose** 父组件直接访问子组件: ```vue <!-- 父组件 --> <Child ref="childRef" /> <script setup> import { ref } from &#39;vue&#39; const childRef = ref() childRef.value.childMethod() // 调用子组件方法 </script> ``` ```vue <!-- 子组件 --> <script setup> defineExpose({ childMethod: () => console.log(&#39;方法暴露&#39;) }) </script> ``` 6. **Provide / Inject** 跨层级组件通信: ```vue <!-- 祖先组件 --> <script setup> import { provide } from &#39;vue&#39; provide(&#39;theme&#39;, &#39;dark&#39;) // 提供数据 </script> ``` ```vue <!-- 后代组件 --> <script setup> import { inject } from &#39;vue&#39; const theme = inject(&#39;theme&#39;, &#39;light&#39;) // 默认值 </script> ``` 7. **事件总线(Event Bus)** 使用第三方库实现全局事件: ```js // eventBus.js import mitt from &#39;mitt&#39; export default mitt() ``` ```vue <!-- 组件A(发送) --> <script setup> import emitter from &#39;./eventBus&#39; emitter.emit(&#39;message&#39;, &#39;Hello!&#39;) </script> ``` ```vue <!-- 组件B(接收) --> <script setup> import emitter from &#39;./eventBus&#39; emitter.on(&#39;message&#39;, (msg) => console.log(msg)) </script> ``` 8. **全局状态管理(Pinia/Vuex)** 集中式状态管理: ```ts // store/counter.js (Pinia) export const useCounterStore = defineStore(&#39;counter&#39;, { state: () => ({ count: 0 }), actions: { increment() { this.count++ } } }) ``` ```vue <!-- 组件使用 --> <script setup> import { useCounterStore } from &#39;./store/counter&#39; const counter = useCounterStore() counter.increment() </script> ``` 9. **作用域插槽(Scoped Slots)** 子组件向父组件模板暴露数据: ```vue <!-- 子组件 --> <slot :item="itemData" /> ``` ```vue <!-- 父组件 --> <Child v-slot="{ item }"> {{ item.name }} </Child> ``` 10. **本地存储通信** 通过Storage API实现数据持久化: ```js // 组件A localStorage.setItem(&#39;sharedData&#39;, JSON.stringify(data)) ``` ```js // 组件B const data = JSON.parse(localStorage.getItem(&#39;sharedData&#39;)) ``` 11. **路由参数通信** 通过URL传递数据: ```js // 发送方 router.push({ path: &#39;/detail&#39;, query: { id: 123 } }) ``` ```vue <!-- 接收方 --> <script setup> import { useRoute } from &#39;vue-router&#39; const route = useRoute() console.log(route.query.id) // 123 </script> ``` 12. **$parent / $children** (不推荐)直接访问组件实例: ```vue <script setup> import { getCurrentInstance } from &#39;vue&#39; const { parent } = getCurrentInstance() parent.doSomething() // 访问父组件方法 </script> ``` 13. **自定义Hook** 复用逻辑的通信方式: ```ts // useSharedData.js import { ref } from &#39;vue&#39; export default function() { const sharedData = ref(null) const updateData = (value) => { sharedData.value = value } return { sharedData, updateData } } ``` ```vue <!-- 组件A/B --> <script setup> import useSharedData from &#39;./useSharedData&#39; const { sharedData, updateData } = useSharedData() </script> ``` --- ### 选择建议 1. **父子组件**:优先使用 `props/emit` 或 `v-model` 2. **兄弟组件**:事件总线/状态管理 3. **深层嵌套**:`provide/inject` 4. **复杂应用**:Pinia全局状态管理 5. **路由相关**:使用路由参数 [^1]: Vue 3组件通信13种方法 [^2]: 透传Attributes ($attrs) [^3]: $parent实例访问 [^4]: 全局组件库引入方式 [^5]: Vue3组件间通信的多种方式
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值