您当前的位置:首页 > 电脑百科 > 程序开发 > 前端

在 Vue.js 中使用事件总线在组件之间传递数据

时间:2023-07-28 20:27:55  来源:51CTO  作者:宇宙一码平川
虽然事件总线最初似乎是组件间通信的便捷方法,但建议探索替代选项,例如provide/inject或全局状态管理。这些替代方案为促进组件之间的通信提供了更强大且可维护的解决方案。

在Vue.js中有一种使用event emitters通过父组件在两个子组件之间进行通信的方法。在子组件中设置事件并在父组件中设置侦听器时,响应式将通过父组件向下传递到嵌套组件。

虽然这是一个有价值的解决方案,但随着项目的发展,它可能会变得笨拙。事件总线是一个 Vue.js 实例,它可以在一个组件中发出事件,然后直接侦听并响应另一个组件中发出的事件——无需父组件的帮助。事件总线比发射器更高效,因为它需要更少的代码来运行。

在本教程中,我们将在 Vue.js 项目中创建一个事件总线,以促进两个组件之间通过私有通道进行通信。这通常称为发布-订阅方法。

先决条件

这篇文章适合所有阶段的开发人员,包括初学者。在阅读本文之前,您应该已经具备以下几点:

  • 已安装版本 14.18+ 及更高版本的Node.js。您可以通过在终端/命令提示符下运行以下命令来验证您是否具有此版本: node -v
  • 安装了 npm 版本 6.x 及更高版本。在终端中使用以下命令验证安装的版本: npm -v
  • Visual Studio Code Editor 或类似的代码编辑器
  • 运行以下命令来搭建 Vite 和 Vue 项目的基架:
# npm 6.x
npm create vite@latest event-bus-tutorial --template vue

# npm 7+, extra double-dash is needed:
npm create vite@latest event-bus-tutorial -- --template vue
  • 导航到 event-bus-tutorial 目录并使用 npm 安装所需的依赖项:
 
cd event-bus-tutorial
npm install

在 Vue 2 中使用事件总线模式

在 Vue 2.x 中,Vue 实例可用于触发通过事件发射器 API($on$off 和$once) 强制附加的处理程序。

为了使用事件总线模式,你所要做的就是创建一个 Vue 构造函数的新实例,将该实例分配给一个名为 eventBus 的常量变量,然后将其导出。这个实例充当事件总线,允许 Vue 应用程序中的不同组件相互通信:

// eventBus.js
const eventBus = new Vue()
export default eventBus

导入 eventBus 实例并在要接收事件的组件中,添加事件侦听器:

 
// ChildComponent.vue
import eventBus from './eventBus'

export default {
  mounted() {
    // adding eventBus listener
    eventBus.$on('custom-event', () => {
      console.log('Custom event triggered!')
    })
  },
  beforeDestroy() {
    // removing eventBus listener
    eventBus.$off('custom-event')
  }
}

导入eventBus实例并在要发送事件的组件中,添加事件发射器:

// ParentComponent.vue
import eventBus from './eventBus'

export default {
  methods: {
    sendCustomEvent() {
      // sending the event
      eventBus.$emit('custom-event')
    }
  }
}

Vue 3 中的事件总线入门

在 Vue 3 中, $on 、 $off  $once 方法已从 Vue 实例中完全删除。因此,为了使用事件总线模式,必须安装外部事件发射器和侦听器包,例如 mitt

使用以下命令安装 mitt 包并开始提供应用程序:

npm install --save mitt
npm run dev

mAIn.js 打开位于目录 src 中的文件,并修改其中的代码,如下所示:

import { createApp } from 'vue'
import mitt from 'mitt'
import App from './App.vue'

const emitter = mitt()
const app = createApp(App)

app.config.globalProperties.emitter = emitter
app.mount('#app')

这段代码通过创建一个发射器实例,使其通过 Vue 应用程序实例全局访问,并将应用程序挂载到 DOM 中,将 mitt 事件发射器库与 Vue 3 应用程序集成。这允许组件使用发射器发出和侦听事件,而无需直接导入。

创建我们的子组件

在我们的演示中,我们将创建两个子组件,它们需要在不使用父组件作为中介的情况下相互通信。首先,在 components 目录中创建一个名为Child1.vue的新文件,并将以下代码块粘贴到其中:

<template>
  <div>
    <button>Increment</button>
  </div>
</template>

<script >
export default {
  name: "Child1",
  data: () => ({
    counter: 0,
  }),
  methods: {},
};
</script>

<style scoped>
button {
  margin: 4rem 0 0;
  padding: 1rem;
  background-color: #0d6efd;
  color: white;
  border-radius: 1rem;
  font-size: 2rem;
}
</style>

总体而言,此代码呈现一个 <div> 包含样式的 <button>。该组件还具有内部数据属性counter 设置为0和空methods属性。

components目录中创建一个名为Child2.vue的新文件,并在其中粘贴以下代码块:

<template>
  <div>
    <h1>{{ counter }}</h1>
  </div>
</template>

<script>
export default {
  name: "Child2",
  data: () => ({
    counter: 0,
  }),
};
</script>

<style scoped>
h1 {
  margin: 5rem 0 0;
  font-size: 10.5rem;
}
</style>

这个 Vue 组件渲染一个 <div> 包含样式标题 <h1> 的组件。该 counter 值动态显示在标题中。

现在,转到您的App.vue文件并将其整个代码替换为以下内容:

<template>
  <div id="app">
    <Child2 />
    <Child1 />
  </div>
</template>
<script>
import Child1 from "./components/Child1.vue";
import Child2 from "./components/Child2.vue";
export default {
  name: "app",
  components: {
    Child1,
    Child2,
  },
};
</script>
<style>
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 5rem;
}
</style>

在 App.vue 组件内部,代码导入并呈现样式化的父 div 中的 Child1Child2 组件。

设置事件

现在,两个组件已准备就绪,您可以在组件中侦听 Child2 事件时,通过在 Child1 组件中发出来设置事件。打开文件 Child1.vue 并将以下代码块复制到其中:

<template>
  <div>
    <button v-on:click="sendEvent">Increment</button>
  </div>
</template>

<script >
export default {
  name: "Child1",
  data: () => ({
    counter: 0,
  }),
  methods: {
    sendEvent() {
      this.counter += 1;
      this.emitter.emit("increment", { msg: this.counter });
    },
  },
};
</script>

<style scoped>
button {
  margin: 4rem 0 0;
  padding: 1rem;
  background-color: #0d6efd;
  color: white;
  border-radius: 1rem;
  font-size: 2rem;
}
</style>

在这里,onclick事件侦听器被添加到 button 元素中。触发此事件时,将调用名为 sendEvent() 的方法。

该方法 sendEvent() 将计数器值递增 1,并使用全局事件发射器向任何父组件或同级组件发出具有更新 counter 值的事件 increment 。

监听和响应事件

设置事件后,我们需要让第二个组件侦听并响应事件。打开文件 Child2.vue 并复制到以下代码块中:

<template>
  <div>
    <h1>{{ counter }}</h1>
  </div>
</template>

<script>
export default {
  name: "Child2",
  data: () => ({
    counter: 0,
  }),
  mounted() {
    this.emitter.on("increment", (data) => {
      this.counter = data.msg;
    });
  },
};
</script>

<style scoped>
h1 {
  margin: 5rem 0 0;
  font-size: 10.5rem;
}
</style>

该代码使用mounted生命周期挂钩在应用程序挂载到 DOM 上时初始化侦听过程。

emitter.on语句现在正在侦听 increment 事件,向下传递data参数,并将其设置为新计数器:

图片

单击组件上的“Increment”按钮时, increment 事件将与更新 counter 的值一起发送到 Child2和 Child1 组件。

Vue.js中事件总线的当前状态

在大多数情况下,不建议使用全局事件总线来促进组件之间的通信。虽然它最初似乎是最简单的解决方案,但随着时间的推移,它经常导致重大的维护挑战。

根据具体情况,Vue 开发团队推荐了几种替代方法,而不是依赖事件总线:

  • 优先使用 props 和事件作为父组件和子组件之间通信的主要方式。如有必要,兄弟姐妹可以通过其共同的父母进行交流
  • 使用provide/inject允许组件及其插槽内容之间的通信。这对于始终一起使用的紧密耦合组件特别有用
  • provide/inject还可以促进组件层次结构中相距甚远的组件之间的通信。它可以帮助消除对props传递过深的需求,其中props通过多个级别的组件向下传递,而这些组件本身不需要这些props本身。
  • 为避免props传递过深,请考虑重构代码库以利用slot。如果中间组件不需要某些props,则可能表明存在责任分离问题。在该组件中引入插槽使父组件能够直接提供内容,从而允许传递 props 而不涉及中间组件
  • 像 Pinia 这样的全局状态管理库可用于跨组件管理全局状态。这些库提供了一种集中的状态管理方法,允许组件访问和修改共享状态,而无需显式传递 prop

总结

这是对 Vue.js 中事件总线的介绍。事件总线充当组件之间易于实现的独立通信,无需通过中央组件或父组件。

虽然事件总线最初似乎是组件间通信的便捷方法,但建议探索替代选项,例如provide/inject或全局状态管理。这些替代方案为促进组件之间的通信提供了更强大且可维护的解决方案。



Tags:Vue.js   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
在 Vue.js 中使用事件总线在组件之间传递数据
虽然事件总线最初似乎是组件间通信的便捷方法,但建议探索替代选项,例如provide/inject或全局状态管理。这些替代方案为促进组件之间的通信提供了更强大且可维护的解决方案。在...【详细内容】
2023-07-28  Search: Vue.js  点击:(333)  评论:(0)  加入收藏
Vue.js 测试端到端指南
本文是一份分步指南,涵盖了 Vue.js 测试基础知识,并为读者解释了如何测试基于 Vue.js 的网站和移动应用程序。“当 Vue 的用户数量达到一定数量时,它就变成了一个社区。突然间,...【详细内容】
2023-03-16  Search: Vue.js  点击:(121)  评论:(0)  加入收藏
分享 7 个好用的 Vue.js 库,建议尽早用上
当我们可以通过使用库轻松实现相同的结果时,为什么还要编写自定义功能?开开发人员最好的朋友和救星就是这些第三方库。我相信一个好的项目会利用一些可用的最佳库。 Vue.js 是...【详细内容】
2023-02-08  Search: Vue.js  点击:(226)  评论:(0)  加入收藏
基于 Vue.js 百度轻量级UI组件库VEUI
今天给小伙伴们分享一个超赞的企业级Vue组件库Veui。 veui:百度前端团队基于 vue.js 构建的企业级应用UI组件库。star达到1k+,超70+组件。 https://github.com/ecomfe/veui...【详细内容】
2022-09-26  Search: Vue.js  点击:(748)  评论:(0)  加入收藏
Vue.js框架学习,创建第一个Vue实例
一、引入Vue.js通过script标签引入vue.js,可以引入本地的js文件,也可以引入网络上的js文件。1、引入本地js文件 2、引入网络js文件 二、关闭Vue开发版本的productionTip提示...【详细内容】
2022-09-26  Search: Vue.js  点击:(355)  评论:(0)  加入收藏
前端开发:Laravel和Vue.JS为什么如此搭?
在应用程序开发的世界中,也存在相互匹配的情况。其中一个匹配是Laravel和Vue.JS&mdash;&mdash;这两个最流行的web开发框架。让我们来看看是什么让这一组合如此富有成效吧! 什...【详细内容】
2022-06-14  Search: Vue.js  点击:(432)  评论:(0)  加入收藏
AngularJS与Vue.JS,2022年选择哪个框架?
JS 只是在路径上运行的平台,这为 Web 开发提供了更强大的选择。Vue.Js、Node.Js、React 和 AngularJS 是一些广泛使用的前端开发框架。所有这些框架都利用 JavaScript 作为开...【详细内容】
2022-03-17  Search: Vue.js  点击:(258)  评论:(0)  加入收藏
高质量 Vue.js UI组件库HeyUI
今天给大家分享一款超优秀的Vue免费开源UI组件库HEYUI。 heyui 一套基于 vue2.x 构建的UI组件库,star高达2.2K+。提供 50 多种丰富的组件,支持全局方法及配置、自定义主题、国...【详细内容】
2020-11-12  Search: Vue.js  点击:(482)  评论:(0)  加入收藏
一篇文章教会你创建vue项目和用vue.js实现数据增删改查
【一、项目背景】在管理员的一些后台页面里,数据列表中都会对这些数据进行增删改查的操作,例如管理员添加商品、修改商品价格、删除商品、查询商品,我们应该关注这些数据的操作...【详细内容】
2020-08-21  Search: Vue.js  点击:(326)  评论:(0)  加入收藏
初学前端框架Vue.js,用vue ui创建项目会不会被鄙视
起初,按照惯例,先在Vue.js官网上看了相关文档介绍及基础使用。 接着在某站上看了某马实战教程,相关环境已准备好,开开心心的在cmd中输入 vue ui,直觉告诉我,事情没那么简单,果然后...【详细内容】
2020-07-14  Search: Vue.js  点击:(430)  评论:(0)  加入收藏
▌简易百科推荐
20k级别前端是怎么使用LocalStorage的,想知道吗?
当咱们把咱们想缓存的东西,存在localStorage、sessionStorage中,在开发过程中,确实有利于咱们的开发,咱们想看的时候也是一目了然,点击Application就可以看到。前言大家好,我是林...【详细内容】
2024-03-26  前端之神  微信公众号  Tags:前端   点击:(11)  评论:(0)  加入收藏
前端不存在了?盲测64%的人更喜欢GPT-4V的设计,杨笛一等团队新作
3 月 9 日央视的一档节目上,百度创始人、董事长兼 CEO 李彦宏指出,以后不会存在「程序员」这种职业了,因为只要会说话,人人都会具备程序员的能力。「未来的编程语言只会剩下两种...【详细内容】
2024-03-11  机器之心Pro    Tags:前端   点击:(9)  评论:(0)  加入收藏
前端开始“锈化”?Vue团队开源JS打包工具:基于Rust、速度极快、尤雨溪主导
Vue 团队已正式开源Rolldown &mdash;&mdash; 基于 Rust 的 JavaScrip 打包工具。Rolldown 是使用 Rust 开发的 Rollup 替代品,它提供与 Rollup 兼容的应用程序接口和插件接口...【详细内容】
2024-03-09  OSC开源社区    Tags:Vue   点击:(11)  评论:(0)  加入收藏
两年前端经验还不会手写Promise?
什么是promise?当我们处理异步操作时,我们经常需要进行一系列的操作,如请求数据、处理数据、渲染UI等。在过去,这些操作通常通过回调函数来处理,但是回调函数嵌套过多会导致代码...【详细内容】
2024-03-07  海燕技术栈  微信公众号  Tags:Promise   点击:(23)  评论:(0)  加入收藏
网站开发中的前端和后端开发有什么区别
前端开发和后端开发都是干什么的?有哪些区别?通俗地讲,前端干的工作是用户可以直接看得见的,而后端开发的工作主要在服务端,用户不太能直接看到。虽然前端开发和后端开发的工作有...【详细内容】
2024-02-21  CarryData    Tags:前端   点击:(31)  评论:(0)  加入收藏
网站程序开发中的前后端分离技术
随着互联网的快速发展和技术的不断创新,传统的网站开发模式已经难以满足日益增长的业务需求。为了提高开发效率、增强系统的可维护性和可扩展性,前后端分离技术逐渐成为了网站...【详细内容】
2024-01-31  网站建设派迪星航    Tags:前后端分离   点击:(23)  评论:(0)  加入收藏
如何优雅的实现前端国际化?
JavaScript 中每个常见问题都有许多成熟的解决方案。当然,国际化 (i18n) 也不例外,有很多成熟的 JavaScript i18n 库可供选择,下面就来分享一些热门的前端国际化库!i18nexti18ne...【详细内容】
2024-01-17  前端充电宝  微信公众号  Tags:前端   点击:(68)  评论:(0)  加入收藏
Vue中Scope是怎么做样式隔离的?
scope样式隔离在 Vue 中,样式隔离是通过 scoped 特性实现的。当在一个组件的 <style> 标签上添加 scoped 特性时,Vue 会自动为这个样式块中的所有选择器添加一个唯一的属性,以...【详细内容】
2024-01-04  海燕技术栈  微信公众号  Tags:Vue   点击:(80)  评论:(0)  加入收藏
vue3中 ref和 reactive的区别 ?
最近有朋友在面试过程中经常被问到这么一个问题,vue3 中的ref 和 reactive的区别在哪里,为什么 要定义两个API 一个 api不能实现 响应式更新吗??带着这个疑问 ,我们 接下来进行逐...【详细内容】
2024-01-03  互联网高级架构师  今日头条  Tags:vue3   点击:(38)  评论:(0)  加入收藏
React18 与 Vue3 全方面对比
1. 编程风格 & 视图风格1.1 编程风格 React 语法少、难度大;Vue 语法多,难度小例如指令:Vue<input v-model="username"/><ul> <li v-for="(item,index) in list" :key="inde...【详细内容】
2024-01-03  爱做梦的程序员  今日头条  Tags:Vue3   点击:(72)  评论:(0)  加入收藏
站内最新
站内热门
站内头条