Vue3中的组件通信发生了哪些变化

Vue3中的组件通信发生了哪些变化已关闭评论

前言

哈喽大家好,我是蛙人。今天给大家分享一篇Vue3组件通信发生了什么变化。

作者:前端铁蛋儿  

来源:https://juejin.cn/post/6997980474535051272


说到Vue3的组件通信,还得从Vue2的组件通信说起, 我们一起来看看Vue3中组件通信跟Vue2发生了哪些变化,小伙伴们查漏补缺哈

基本使用

首先我们来看下组件的几种用法循序渐进:

Vue2的用法总结下帮助小伙伴们加深下记忆,如果还没不是很熟悉基础的小伙伴可以去看下官网。

父子组件通信

  • props 父到子
  • $emit 子到父
  • ref$refs 子到父
  • $parent 子到父
  • $children 父到子 (Vue3此方法作废)

多层级父子组件通信

  • provide、inject父到子或者子到父
// provide 声明
provide() {
  return {
    title'我是app',
    ComAppthis
  }
}
// inject 使用
// 使用的时候可以拿到父组件的this也就是ComApp进行传递数据
 inject: ['title''ComApp'], 

  • $attrs 利用属性的传递数据配合inheritAttrs使用
  • $listeners (Vue3此方法作废监听功能是 attrs的一部分)

非关系组件通信(EventBus也称为事件总线)

Vue2的EventBus

eventBus.js

const 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事件应该是父子组件之间沟通的首选。兄弟节点可以通过它们的父节点通信。
  • Provideinject允许一个组件与它的插槽内容进行通信。这对于总是一起使用的紧密耦合的组件非常有用。
  • provide/inject 也能够用于组件之间的远距离通信。它可以帮助避免“prop 逐级透传”,即 prop 需要通过许多层级的组件传递下去,但这些组件本身可能并不需要那些 prop。
  • Prop 逐级透传也可以通过重构以使用插槽来避免。如果一个中间组件不需要某些 prop,那么表明它可能存在关注点分离的问题。在该类组件中使用 slot 可以允许父节点直接为它创建内容,因此 prop 可以被直接传递而不需要中间组件的参与。
  • 全局状态管理,比如 Vuex

Vuex

<template>
    //store.state.count取值
  <div>{{ $store.state.count }}</div>
  <button @click="myCommit ">点击</button>
</template>
<script setup lang="ts">
  import { useStore } from 'vuex';
  const store = useStore();

  /
/commit提交
  const myCommit = () =>{
    store.commit("commitValue")
  }
</
script>

组件通信最好用的还是Vuex, 但是多多少少还是存在一些问题。

Vuex唯有一点不好就是TypeScript的支持问题:

  • 不用TypeScript时候在调用stategettersmutationdispatch的时候没有智能提示,那么多文件可找吧!!!!!
  • 用了TypeScript以后发现解决这个问题,但是发现VuexTypeScriptTypes支持并没有想想中的那么香(这里说的是Vuex4)。

虽然Vuex4提供了useStore函数, 但是并没有对store做的像redux那样丝滑的推导体验。

有人的想法非常棒,把Vuex的store初始化的时候重新扩展了下,这样就能很好的获得TypeScript对Vuex的各种支持。

其实Vuex团队也意识到这个问题, 在Vuex5的时候改纯函数写法了,这样就能很好的支持TypeScript

Vuex5已经到RC阶段, 现阶段我们可以尝试使用 Pinia

Pinia

官网 PiniaVue.js 的轻量级状态管理库,最近很受欢迎。

类似Vuex, 是Vue的另一种状态管理方案,Pinia 支持 Vue2Vue3以及更好的支持TypeScript

使用

创建Pinia传递给app

// 使用pinia
import { createPinia } from 'pinia';
const app = createApp(App)
// 挂到app上
app.use(createPinia())
app.mount('#app')

创建Store

import { defineStore } from "pinia";

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

组件中使用Stroe

<template>
  <div>
    {{store.count}}
  </div>

</template>

<script>
  import { defineComponent } from 'vue'
  import { useStore } from './
store/store.js'
  export default defineComponent({
    name: '
App',
    setup() {
      // 调用函数 获得Store
      const store = useStore()
      return {
        store,
      }
    },
  })
</script>

篇幅原因在这就不啰嗦了, 感兴趣的小伙伴可以去官网上好好看看api

Vuex 和 Pinia 的优缺点

Vuex的优点:

  • 支持调试功能,如时间旅行和编辑
  • 适用于大型、高复杂度的Vue.js项目

Vuex的缺点

  • Vue 3 开始,getter 的结果不会像计算属性那样缓存
  • Vuex 4有一些与类型安全相关的问题

Pinia的优点

  • 完整的 TypeScript 支持:与在 Vuex 中添加 TypeScript 相比,添加 TypeScript 更容易
  • 极其轻巧(体积约 1KB)
  • storeaction 被调度为常规的函数调用,而不是使用 dispatch 方法或 MapAction 辅助函数,这在 Vuex 中很常见
  • 支持多个Store
  • 支持 Vue devtoolsSSRwebpack 代码拆分

Pinia的缺点

  • 不支持时间旅行和编辑等调试功能

何时使用Pinia,何时使用Vuex

  • Pinea是轻量级的,体积很小,它适合于中小型应用。它也适用于低复杂度的Vue.js项目,因为一些调试功能,如时间旅行和编辑仍然不被支持。
  • Vuex 用于中小型 Vue.js 项目是过度的,因为它重量级的,对性能降低有很大影响。因此,Vuex 适用于大规模、高复杂度的 Vue.js 项目。


谢谢你读完本篇文章,有帮助的话请❤️关注+点赞+收藏+评论+转发❤️

  • 关注后回复学习资料免费领取视频教程
  • 关注后回复加群拉你进技术交流群
  • 欢迎关注前端娱乐圈,更多「前端开发技巧」只在公众号推送

往期推荐

VSCode 的这些黑科技 99% 的人都不知道

还在用原型函数编程吗,快来认识一下ES6类吧!

深入浅出 Commonjs 和 Es Module区别 – 面试必问

盘点Vue3那些有趣的API



来源: 前端娱乐圈