Vue组件通信最全篇
说到Vue3的组件通信,还得从Vue2的组件通信说起, 小伙伴们查漏补缺哈
文章图片
首先我们来看下组件的几种用法循序渐进:
Vue2的用法总结下帮助小伙伴们加深下记忆,如果还没不是很熟悉基础的小伙伴可以去看下官网。
- 父子组件通信
- props 父到子
- $emit 子到父
- ref、$refs 子到父
- $parent 子到父
- $children 父到子 (Vue3此方法作废)
- 多层级父子组件通信
- provide、inject 父到子 或者 子到父
// provide 声明 provide() { return { title: '我是app', ComApp: this, } } // inject 使用 // 使用的时候可以拿到父组件的this也就是ComApp进行传递数据 inject: ['title', 'ComApp'],
- $attrs 利用属性的传递数据配合inheritAttrs使用
- $listeners (Vue3此方法作废监听功能是 attrs的一部分)
- provide、inject 父到子 或者 子到父
- 非关系组件通信(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中完全移除了
Vue3的EventBus:$on
、$off
和$once
方法。$emit
仍然包含于现有的 API 中,因为它用于触发由父组件声明式添加的事件处理函数。
// 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。
- Vuex
//store.state.count取值 {{ $store.state.count }}
组件通信最好用的还是Vuex, 但是多多少少还是存在一些问题。
Vuex唯有一点不好就是TypeScript的支持问题:
- 不用TypeScript时候在调用state、getters、mutation、dispatch的时候没有智能提示,那么多文件可找吧!!!!!
- 用了TypeScript以后发现解决这个问题,但是发现Vuex对TypeScript的Types支持并没有想想中的那么香(这里说的是Vuex4)。
有人的想法非常棒,把Vuex的store初始化的时候重新扩展了下,这样就能很好的获得TypeScript对Vuex的各种支持。
其实Vuex团队也意识到这个问题, 在Vuex5的时候改纯函数写法了,这样就能很好的支持TypeScript。
文章图片
Vuex5已经到RC阶段, 现阶段我们可以尝试使用 Pinia
5.Pinia(官网)
Pinia 是 Vue.js 的轻量级状态管理库,最近很受欢迎。
类似 Vuex, 是 Vue 的另一种状态管理方案,Pinia 支持 Vue2 和 Vue3以及更好的支持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: () => ({ count: 1 }), });
- 组件中使用Stroe
{{store.count}}
篇幅原因在这就不啰嗦了, 感兴趣的小伙伴可以去官网上好好看看api
- Vuex 和 Pinia 的优缺点
Vuex的优点
- 支持调试功能,如时间旅行和编辑
- 适用于大型、高复杂度的Vue.js项目
- 从 Vue 3 开始,getter 的结果不会像计算属性那样缓存
- Vuex 4有一些与类型安全相关的问题
- 完整的 TypeScript 支持:与在 Vuex 中添加 TypeScript 相比,添加 TypeScript 更容易
- 极其轻巧(体积约 1KB)
- store 的 action 被调度为常规的函数调用,而不是使用
dispatch
方法或MapAction
辅助函数,这在 Vuex 中很常见 - 支持多个Store
- 支持 Vue devtools、SSR 和 webpack 代码拆分
- 不支持时间旅行和编辑等调试功能
- 何时使用Pinia,何时使用Vuex
- Pinea是轻量级的,体积很小,它适合于中小型应用。它也适用于低复杂度的Vue.js项目,因为一些调试功能,如时间旅行和编辑仍然不被支持。
- Vuex 用于中小型 Vue.js 项目是过度的,因为它重量级的,对性能降低有很大影响。因此,Vuex 适用于大规模、高复杂度的 Vue.js 项目。
文章图片
欢迎大佬们留言指正,坚持每天进步一点点。
【Vue组件通信最全篇】
文章图片
推荐阅读
- Docker应用:容器间通信与Mariadb数据库主从复制
- vue-cli|vue-cli 3.x vue.config.js 配置
- 2020-04-07vue中Axios的封装和API接口的管理
- VueX--VUE核心插件
- Unity和Android通信系列文章2——扩展UnityPlayerActivity
- 动态组件与v-once指令
- Android|Android BLE蓝牙连接异常处理
- vue组件中为何data必须是一个函数()
- 用npm发布一个包的教程并编写一个vue的插件发布
- (六)Component初识组件