Vue组件通信最全篇

说到Vue3的组件通信,还得从Vue2的组件通信说起, 小伙伴们查漏补缺哈
Vue组件通信最全篇
文章图片

首先我们来看下组件的几种用法循序渐进:
Vue2的用法总结下帮助小伙伴们加深下记忆,如果还没不是很熟悉基础的小伙伴可以去看下官网。

  1. 父子组件通信
    • props 父到子
    • $emit 子到父
    • ref、$refs 子到父
    • $parent 子到父
    • $children 父到子 (Vue3此方法作废)
  2. 多层级父子组件通信
    • provide、inject 父到子 或者 子到父
      // provide 声明 provide() { return { title: '我是app', ComApp: this, } } // inject 使用 // 使用的时候可以拿到父组件的this也就是ComApp进行传递数据 inject: ['title', 'ComApp'],

    • $attrs 利用属性的传递数据配合inheritAttrs使用
    • $listeners (Vue3此方法作废监听功能是 attrs的一部分)
  3. 非关系组件通信(EventBus也称为事件总线)
    Vue2的EventBus:
    // eventBus.jsconst eventBus = new Vue()export default eventBus

    // ChildComponent.vue import eventBus from './eventBus'export default { mounted() { // 添加 eventBus 监听器 eventBus.$on('custom-event', () => { console.log('Custom event triggered!') }) }, beforeDestroy() { // 移除 eventBus 监听器 eventBus.$off('custom-event') } }

    // ParentComponent.vue import eventBus from './eventBus'export default { methods: { callGlobalCustomEvent() { eventBus.$emit('custom-event') // 当 ChildComponent 被挂载,控制台中将显示一条消息 } } }

    ? Vue3中完全移除了 $on$off$once 方法。 $emit 仍然包含于现有的 API 中,因为它用于触发由父组件声明式添加的事件处理函数。
    Vue3的EventBus:
    // main.js import mitt from 'mitt'let app = createApp(App)app.config.globalProperties.$myhub = new mitt()

    // ParentComponent.vue export default { // ..... methods: { getattrs() { this.$myhub.emit('myhub', '我是小白龙') } }

    // ChildComponent.vue export default { // ..... mounted() { this.$myhub.on('myhub', (data) => { console.log(data) // 我是小白龙 }) }, }

    总结:
    在绝大多数情况下,不鼓励使用全局的 event bus 在组件之间进行通信。虽然在短期内往往是最简单的解决方案,但从长期来看,它维护起来总是令人头疼。根据具体情况来看,有多种 event bus 的替代方案:
    • Prop 和事件应该是父子组件之间沟通的首选。兄弟节点可以通过它们的父节点通信。
    • Provide 和 inject 允许一个组件与它的插槽内容进行通信。这对于总是一起使用的紧密耦合的组件非常有用。
    • provide/inject 也能够用于组件之间的远距离通信。它可以帮助避免“prop 逐级透传”,即 prop 需要通过许多层级的组件传递下去,但这些组件本身可能并不需要那些 prop。
    • Prop 逐级透传也可以通过重构以使用插槽来避免。如果一个中间组件不需要某些 prop,那么表明它可能存在关注点分离的问题。在该类组件中使用 slot 可以允许父节点直接为它创建内容,因此 prop 可以被直接传递而不需要中间组件的参与。
    • 全局状态管理,比如 Vuex。
  4. Vuex

    组件通信最好用的还是Vuex, 但是多多少少还是存在一些问题。
    Vuex唯有一点不好就是TypeScript的支持问题:
    • 不用TypeScript时候在调用state、getters、mutation、dispatch的时候没有智能提示,那么多文件可找吧!!!!!
    • 用了TypeScript以后发现解决这个问题,但是发现Vuex对TypeScript的Types支持并没有想想中的那么香(这里说的是Vuex4)。
    虽然Vuex4提供了useStore函数, 但是并没有对store做的像redux那样丝滑的推导体验。
    有人的想法非常棒,把Vuex的store初始化的时候重新扩展了下,这样就能很好的获得TypeScript对Vuex的各种支持。
    其实Vuex团队也意识到这个问题, 在Vuex5的时候改纯函数写法了,这样就能很好的支持TypeScript。
Vue组件通信最全篇
文章图片

Vuex5已经到RC阶段, 现阶段我们可以尝试使用 Pinia
5.Pinia(官网)
Pinia 是 Vue.js 的轻量级状态管理库,最近很受欢迎。
类似 Vuex, 是 Vue 的另一种状态管理方案,Pinia 支持 Vue2 和 Vue3以及更好的支持TypeScript。
使用:
  1. 创建Pinia传递给app
    // 使用pinia import { createPinia } from 'pinia'; const app = createApp(App) // 挂到app上 app.use(createPinia()) app.mount('#app')

  2. 创建Store
    import { defineStore } from "pinia"; // defineStore 调用后返回一个函数,调用该函数获得 Store 实体 export const useStore = defineStore({ // id: 必须的,在所有 Store 中唯一 id: "myGlobalState", // state: 返回对象的函数 state: () => ({ count: 1 }), });

  3. 组件中使用Stroe

    篇幅原因在这就不啰嗦了, 感兴趣的小伙伴可以去官网上好好看看api
  4. Vuex 和 Pinia 的优缺点
    Vuex的优点
    • 支持调试功能,如时间旅行和编辑
    • 适用于大型、高复杂度的Vue.js项目
    Vuex的缺点
    • 从 Vue 3 开始,getter 的结果不会像计算属性那样缓存
    • Vuex 4有一些与类型安全相关的问题
    Pinia的优点
    • 完整的 TypeScript 支持:与在 Vuex 中添加 TypeScript 相比,添加 TypeScript 更容易
    • 极其轻巧(体积约 1KB)
    • store 的 action 被调度为常规的函数调用,而不是使用 dispatch 方法或 MapAction 辅助函数,这在 Vuex 中很常见
    • 支持多个Store
    • 支持 Vue devtools、SSR 和 webpack 代码拆分
    Pinia的缺点
    • 不支持时间旅行和编辑等调试功能
  5. 何时使用Pinia,何时使用Vuex
    • Pinea是轻量级的,体积很小,它适合于中小型应用。它也适用于低复杂度的Vue.js项目,因为一些调试功能,如时间旅行和编辑仍然不被支持。
    • Vuex 用于中小型 Vue.js 项目是过度的,因为它重量级的,对性能降低有很大影响。因此,Vuex 适用于大规模、高复杂度的 Vue.js 项目。
Vue组件通信最全篇
文章图片

欢迎大佬们留言指正,坚持每天进步一点点。
【Vue组件通信最全篇】Vue组件通信最全篇
文章图片

    推荐阅读