在看 https://v3-migration.vuejs.org/breaking-changes/events-api.html

在vue2里面

In 2.x, a Vue instance could be used to trigger handlers attached imperatively via the event emitter API ($on, $off and $once). This could be used to create an event bus to create global event listeners used across the whole application:

// eventBus.js

const eventBus = new Vue()

export default eventBus

直接在项目使用

eventBus.$on('custom-event', () => {//TODO})

eventBus.$emit('custom-event')

但是,vue3移除了

We removed $on, $off and $once methods from the instance completely. $emit is still a part of the existing API as it's used to trigger event handlers declaratively attached by a parent component.

The event bus pattern can be replaced by using an external library implementing the event emitter interfacefor example mitt or tiny-emitter.

所以只能找第三方库,官方推荐有2个,特意对比了下

mitt vs tiny-emitter

https://www.npmtrends.com/tiny-emitter-vs-mitt

mitt 和 tiny-emitter 对比分析

共同点

  1. 都支持on(type, handler)、off(type, [handler])和emit(type, [evt])三个方法来注册、注销、派发事件

不同点

  • emit

    1. 有 all 属性,可以拿到对应的事件类型和事件处理函数的映射对象,是一个Map不是{}

    2. 支持监听'*'事件,可以调用emitter.all.clear()清除所有事件

    3. 返回的是一个对象,对象存在上面的属性

  • tiny-emitter

    1. 支持链式调用, 通过e属性可以拿到所有事件(需要看代码才知道)

    2. 多一个 once 方法 并且 支持设置 this(指定上下文 ctx)

    3. 返回的一个函数实例,通过修改该函数原型对象来实现的

更多参看:mitter事件派发---mitt和tiny-emitter源码分析https://juejin.cn/post/7022851362568454157

看官方代码案例是tiny-emitter

$emit 目前只能从子组件向父组件传值了,event Bus 只有借助第三方库了

// eventBus.js
import emitter from 'tiny-emitter/instance'
export default {
  $on: (...args) => emitter.on(...args),
  $once: (...args) => emitter.once(...args),
  $off: (...args) => emitter.off(...args),
  $emit: (...args) => emitter.emit(...args)}

具体参看:https://github.com/scottcorgan/tiny-emitter

但是个人推荐 使用mitt

mitt.js使用

mitt 的用法和 EventEmitter 类似,通过 on 方法添加事件,off 方法移除,clear 清空所有。

import mitt from 'mitt'

const emitter = mitt()

// listen to an event
emitter.on('foo', e => console.log('foo', e) ) // listen to all events
emitter.on('*', (type, e) => console.log(type, e) ) // fire an event
emitter.emit('foo', { a: 'b' })
// clearing all events
emitter.all.clear()

这里安利一下:《原生js实现事件监听类on/emit/off方法,Vue event事件机制解读

mitt基于事件总线的订阅发布模式,任意组件之间都可以通信。provide/inject 在非组件中(一般用于子孙组件传值),就没法用了。

在绝大多数情况下,不鼓励使用全局的事件总线在组件之间进行通信。虽然在短期内往往是最简单的解决方案,但从长期来看,它维护起来总是令人头疼。根据具体情况来看,有多种事件总线的替代方案:

  • props / emit 应该是父子组件之间沟通的首选。兄弟节点可以通过它们的父节点通信。

  • Provide 和 inject 允许一个组件与它的插槽内容进行通信。这对于总是一起使用的紧密耦合的组件非常有用。

  • provide/inject 也能够用于组件之间的远距离通信。它可以帮助避免“prop 逐级透传”,即 prop 需要通过许多层级的组件传递下去,但这些组件本身可能并不需要那些 prop。

  • Prop 逐级透传也可以通过重构以使用插槽来避免。如果一个中间组件不需要某些 prop,那么表明它可能存在关注点分离的问题。在该类组件中使用 slot 可以允许父节点直接为它创建内容,因此 prop 可以被直接传递而不需要中间组件的参与。

  • 全局状态管理,比如 Vuex

具体到插件如何用呢?

全局总线

import { createApp } from 'vue';
import App from './App.vue';
import mitt from "mitt" const app = createApp(App)
app.config.globalProperties.$mybus = mitt()

vue2、vue3 ,个人都不推荐这种模式,即使要这种方式,推荐用:

import { createApp } from "vue";
import App from "./App.vue"; import mitt from 'mitt';                  // Import mitt
const emitter = mitt();                   // Initialize mitt const app = createApp(App);
app.provide('emitter', emitter);          //  Provide as `emitter`
app.mount('#app');

在子组件

import { inject } from 'vue'

export default {
  setup() {
    const emitter = inject("emitter"); // Inject `emitter`
    const mymethod = () => {
      emitter.emit("myevent", 100);
    };
    return {
      mymethod
    }
  }
}

任意组件都可以inject 出来,直接用。

封装自定义事务总线文件 mybus.js

创建新的 js 文件,在任何你想使用的地方导入即可。

import mitt from 'mitt';
type Events = {
  menuDrag?: DragEvent;
  menuDragend?: DragEvent;
}; const Bus = mitt<Events>(); export default Bus;

子组件使用

onMounted(() => {
  Bus.on('menuDrag', (e: DragEvent) => {
    drag(e);
  });
  Bus.on('menuDragend', (e: DragEvent) => {
    dragend(e);
  });
});

推荐使用此种模式

直接在组件里面导入使用

因为分散式更方便管理和排查问题。

import mitt from 'mitt'
export default {
  setup (props) {
    const formItemMitt = mitt()
    return {
      formItemMitt
    }
  }
}

组合式API推荐这种模式

不管那种方式,Vue 3 都建议在 beforeUnmount 移除监听(vue2在beforeDestroy移除)

参考文章:

Vue3.x 推荐使用 mitt.js https://juejin.cn/post/6973106775755063333

vue3:兄弟组件,跨组件传值,事件总线的通信方式(mitt / tiny-emitter) https://blog.csdn.net/qq_42543244/article/details/123806588

Vue 3 Event Bus with Composition API https://javascript.tutorialink.com/vue-3-event-bus-with-composition-api/

转载本站文章《vue2升级vue3: Event Bus 替代方案—— mitt》,
请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/vue3/8837.html

vue2升级vue3: Event Bus 替代方案的更多相关文章

  1. vue2升级vue3指南(二)—— 语法warning&error篇

    本文总结了vue2升级vue3可能会遇到的语法警告和错误,如果想知道怎样升级,可以查看我的上一篇文章:vue2升级vue3指南(一)-- 环境准备和构建篇 Warning 1.deep /deep/和 ...

  2. vue2升级vue3:vue2 vue-i18n 升级到vue3搭配VueI18n v9

    项目从vue2 升级vue3,VueI18n需要做适当的调整.主要是Vue I18n v8.x 到Vue I18n v9 or later 的变化,其中初始化: 具体可以参看:https://vue- ...

  3. vue2升级vue3:Vue Demij打通vue2与vue3壁垒,构建通用组件

    如果你的vue2代码之前是使用vue-class-component 类组件模式写的.选择可以使用 https://github.com/facing-dev/vue-facing-decorator ...

  4. vue2升级vue3:vue-i18n国际化异步按需加载

    vue2异步加载之前说过,vue3还是之前的方法,只是把 i18n.setLocaleMessage改为i18n.global.setLocaleMessage 但是本文还是详细说一遍: 为什么需要异 ...

  5. uniapp项目vue2升级vue3简单记录

    看到好多开源项目都升级了vue3,看文章说vue3性能升级很多,而且组合式api很香,遂把最近开发的自助洗车app升级下,在此记录下出现的问题. uniapp升级vue3官方指南 我是先去vue官网看 ...

  6. vue2升级vue3指南(一)—— 环境准备和构建篇

    1.nodejs和npm 注意二者的版本,版本过低需要升级,本人升级后的版本如下: $ node -v v16.15.1 $ npm -v 8.11.0 2.package.json 和依赖升级 由于 ...

  7. Akka源码分析-Event Bus

    akka中的EventBus其实是不常用,也最容易被忽略的一个组件. 但如果你深入Cluster的实现就会发现,这个东西其实还挺有用的,而且它是ActorSystem系统中所有事件消息的一个横切面,通 ...

  8. Vue2和Vue3技术整理1 - 入门篇 - 更新完毕

    Vue2 0.前言 首先说明:要直接上手简单得很,看官网熟悉大概有哪些东西.怎么用的,然后简单练一下就可以做出程序来了,最多两天,无论Vue2还是Vue3,就都完全可以了,Vue3就是比Vue2多了一 ...

  9. 盘点Vue2和Vue3的10种组件通信方式(值得收藏)

    Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异:本文将通过选项式API 组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式.其中将要实现的通信 ...

  10. Vue2 到 Vue3,重温这 5 个常用的 API

    距离Vue3发布已经过去一年多时间了,从Vue2到Vue3是一个不小的升级,包括周边生态等.虽然目前大多数开发者们在使用的仍旧以Vue2为准,但Vue3显然是Vue开发者们未来必须面对的,而且前不久V ...

随机推荐

  1. YbtOJ 数位DP G.幸运666

    日常写点奇奇怪怪的乱搞做法 awa 这题跟前面几道数位 DP 的区别在于让求第 \(n\) 小的数. 虽然我不会求也不想学这个,但我们可以 binary search! 问题就转换为求 \([1,mi ...

  2. Go语言基准测试(benchmark)三部曲之一:基础篇

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 关于基准测试(benchmark) Go的标准库内置的 ...

  3. 深度解析NLP文本摘要技术:定义、应用与PyTorch实战

    在本文中,我们深入探讨了自然语言处理中的文本摘要技术,从其定义.发展历程,到其主要任务和各种类型的技术方法.文章详细解析了抽取式.生成式摘要,并为每种方法提供了PyTorch实现代码.最后,文章总结了 ...

  4. UIPath流程控制

    应当仔细地观察,为的是理解:应当努力地理解,为的是行动.   UIPath程序中流程控制主要包括条件语句.循环语句以及中断语句.下面我们一一学习这些语句在RPA流程设计中的使用. 1. 条件判断 if ...

  5. 生产实践:Redis与Mysql的数据强一致性方案

    公众号「架构成长指南」,专注于生产实践.云原生.分布式系统.大数据技术分享. 数据库和Redis如何保持强一致性,这篇文章告诉你 目的 Redis和Msql来保持数据同步,并且强一致,以此来提高对应接 ...

  6. 企业ERP和泛微OA集成场景分析

    轻易云数据集成平台(qeasy.cloud)为企业ERP和泛微OA系统提供了强大的互通解决方案,特别在销售.采购和库存领域的单据审批场景中表现出色.这些场景涉及到多个业务单据的创建和审批,以下是一些具 ...

  7. preparedStatement.setObject()为什么要这样写?

    setObject就是给JDBC的SQL语句的占位符赋值的,即是下面的"?" 预编译的SQL:参数使用?作为占位符 注意:sql的参数使用?作为占位符. 如: select * f ...

  8. ES到底是个什么东西

    概念:全文检索服务器(是基于Lucene开发的全文检索服务器),它可以近乎实时存储.检索数据,底层仍然是Lucene来实现的所以索引和搜索功能,他的目的是通过的简单的RESTFul API 来隐藏Lu ...

  9. 快速认识什么是:Docker

    Docker,一种可以将软件打包到容器中并在任何环境中可靠运行的工具.但什么是容器以及为什么需要容器呢?今天就来一起学快速入门一下Docker吧!希望本文对您有所帮助. 假设您使用 Cobol 构建了 ...

  10. 基于DotNetty实现自动发布 - 自动检测代码变化

    前言 很抱歉没有实现上一篇的目标:一键发布,因为工作量超出了预期,本次只实现了 Git 代码变化检测 已完成的功能 解决方案的项目发现与配置 首次发布需要手动处理 自动检测代码变化并解析出待发布的文件 ...