经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
Vue3中事件总线的具体使用
来源:jb51  时间:2023/4/12 11:14:41  对本文有异议

导读

在Vue2中,我们遇到复杂的组件通信时,经常采用事件总线的方式来通信。其具体的思路就是实例化一个空白的Vue,并通过其提供的$on$once$emit方法来进行通信。而在Vue3中,上述三个API已经被移除了,那么我们又如何使用事件总线呢?

事件总线的本质

Vue2中的$on$once$emit本质上就是其内部实现了一个EventEmitter(事件派发器),每一个事件都和若干回调相对应,只要事件被触发,那么就将执行此事件所有对应的回调。同时,在JavaScript中,该思想被广泛地使用,尤其在Node.js的事件机制中,就是创建了一个EventEmitter实例,具体请自行查阅相关资料。因此,我们只需要实现一个简单的EventEmitter,并全局传递到每一个组件中,就可以实现一个事件总线了。而全局传递,我们可以使用config.globalProperties绑定到每一个组件,也可以在根组件(main)中,通过provide提供总线,需要使用的组件使用inject注入。下面就让我们来实现一下吧。

构建一个EventEmitter

由于我们可能会有多条总线,我们还是把EventEmitter写成类的方式,每一条总线都将是一个EventEmitter实例。以下是EventEmitter的简单实现,其只实现了ononceemit三个API。

  1. class EventEmitter{
  2. constructor(){
  3. this.callbacks={};
  4. }
  5. on(envetName,callback){
  6. if(!Array.isArray(this.callbacks[envetName])){
  7. this.callbacks[envetName]=[];
  8. }
  9. this.callbacks[envetName].push(callback);
  10. }
  11. emit(eventName,...args){
  12. if(Array.isArray(this.callbacks[eventName])){
  13. this.callbacks[eventName].forEach(callback=>callback(...args));
  14. }
  15. }
  16. off(eventName,callback){
  17. if(!Array.isArray(this.callbacks[eventName])){
  18. return
  19. }
  20. if(callback){
  21. this.callbacks[eventName].forEach(cb=>{
  22. if(callback===cb){
  23. this.callbacks[eventName].splice(this.callbacks[eventName].indexOf(callback),1);
  24. }
  25. });
  26. } else{
  27. this.callbacks[eventName]=[];
  28. }
  29. }
  30. once(eventName,callback){
  31. const that=this;
  32. const fn=function(){
  33. callback.apply(that,[...arguments]);
  34. that.off(eventName,fn);
  35. }
  36. that.on(eventName,fn);
  37. }
  38. }

具体的代码基本上还是很好理解的,就不在本文解释了,具体请自行查阅相关的资料。

将EventEmitter实例化并全局引入

上文已经说了有两种引入EventEmitter的方法,这里简单地给个参考实例吧。

config.globalProperties方法

在main.js中

  1. import { createApp } from 'vue'
  2. import './style.css'
  3. import App from './App.vue'
  4. const app=createApp(App);
  5. app.config.globalProperties.$event=new EventEmitter();
  6. app.mount('#app')

在组件中:

  1. //Comp1
  2. <script setup>
  3. import {getCurrentInstance} from "vue"
  4. const vm=getCurrentInstance();
  5. vm.proxy.$event.on('test',()=>{
  6. console.log('test event emit!')
  7. })
  8. </script>
  9.  
  10. //Comp2
  11. <script setup>
  12. import {getCurrentInstance} from "vue"
  13. const vm=getCurrentInstance();
  14. vm.proxy.$event.emit('test',"a","b")
  15. </script>

但这种方法不太优雅,不方便定义多条总线,建议使用下述的方法。

provide/inject

在main.js中

  1. provide("eventBus1",new EventEmitter());
  2. provide("eventBus2",new EventEmitter());

在组件中

  1. //Comp1
  2. <script setup>
  3. import {inject} from "vue";
  4. const bus1=inject("eventBus1")
  5. bus1.on("bus1-on-event",()=>{
  6. console.log('eventBus1 on event emit!')
  7. })
  8. </script>
  9. //Comp2
  10. <script setup>
  11. import {inject} from "vue";
  12. const bus1=inject("eventBus1")
  13. const bus2=inject("eventBus2")
  14. bus2.on("bus2-on-event",()=>{
  15. console.log('eventBus2 on event emit!')
  16. })
  17. bus1.emit("bus1-on-event")
  18. </script>
  19. //Comp3
  20. <script setup>
  21. import {inject} from "vue";
  22. const bus2=inject("eventBus2")
  23. bus2.emit("bus2-on-event")
  24. </script>

此方法中,使用inject也比使用getCurrentInstance.proxy更优雅一些,且不使用就不必使用inject注入。

结束语

到此这篇关于Vue3中事件总线的具体使用的文章就介绍到这了,更多相关Vue3 事件总线内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号