zoukankan      html  css  js  c++  java
  • Vue组件通信中事件总线(eventBus)的使用

      之前公司的项目中使用 eventBus 进行组件通信时遇到了一些数据渲染时的问题,下面对遇到的这些问题做下简单的介绍以及解决方法。

      我们都知道,在 Vue 中,组件通信的方式有很多,而针对那些没有父子级关系或者任何关系的组件要实现通信(数据传递)的方法就是使用 Vuex 或者 eventBus(事件总线),具体应该选择哪一种还要看实际情况。公司的项目中两种方法都有使用,而自己当时对 Vuex 的使用还不是很熟悉,所以就选择了 eventBus 来实现组件通信。然而在开发过程中还是遇到了一些问题。

      首先来看下项目中要实现的效果:

      大致需求是这样:左边地图组件和右边视图组件需要关联,点击左边时需要发送 机器告警(图)的数据机器缺陷(图)的数据 给视图组件,而,右边视图组件中有一个公共的组件用来展示数据,用户通过点击 “机器告警” 或者 “机器缺陷” 按钮来获得对应的图示。

     

      robotState.vue 中的 html 代码(部分):

     1 <template>
     2   <div>
     3     <section class="the-wrapper">
     4       <h2 class="title">
     5         <span @click="switchView" :class="xxxx"></span>
     6         <span class="switch-btn" :class="{ active: currentTab === 1 }" @click="switchTab(1)">机器告警</span>
     7         <span class="switch-btn" :class="{ active: currentTab === 2 }" @click="switchTab(2)">机器缺陷</span>
     8       </h2>
     9     </section>
    10     <!-- 机器告警图(表) -->
    11     <section v-if="currentTab === 1" :key="0" style="xxxx">
    12       <transition enter-active-class="animated slideInLeft">
    13         <v-canvas-pie v-if="isPieView" ref="pie" />
    14         <v-table v-else ref="table" />
    15       </transition>
    16     </section>
    17      <!-- 机器缺陷图(表) -->
    18     <section v-if="currentTab === 2" :key="1" style="xxxx">
    19       <transition enter-active-class="animated slideInLeft">
    20         <v-canvas-pie v-if="isPieView" ref="pie" />
    21         <v-table v-else ref="table" />
    22       </transition>
    23     </section>
    24   </div>
    25 </template>

      map.js 中的逻辑(部分):

     1 getData = async (city) => {
     2     // 机器告警(图)
     3     axios.post('xxxxxxxxxxxxx',{id:city.code})
     4         .then(res=>{
     5            res.data.map(item=>{
     6                Bus.$emit('AlarmInfoPie',[
     7                 { name:"正常",value:item.normal },
     8                 { name:"一般",value:item.commonly },
     9                 { name:"严重",value:item.serious },
    10                 { name:"危急",value:item.critical },
    11                ])
    12            }) 
    13         })
    14 
    15     // 机器缺陷(图)
    16     axios.post('mmmmmmmmmmmmmmm',{id:city.code})
    17     .then(res=>{
    18         res.data.map(item=>{
    19             Bus.$emit('defectPie',[
    20              { name:"无缺陷",value:item.normal },
    21              { name:"一般缺陷",value:item.commonly },
    22              { name:"严重缺陷",value:item.serious },
    23              { name:"危急缺陷",value:item.critical },
    24             ])
    25         }) 
    26     })
    27 }

      robotState.vue 中的逻辑(部分):

     1 export default {
     2     components:{
     3         VCanvasPie,
     4         VTable
     5     },
     6     data(){
     7         return {
     8             isPieView:true,
     9             currentTab:1,
    10         }
    11     },
    12     methods: {
    13         // 机器告警(图)
    14         async getRobotAlarmPie(){ 
    15             let temp,       // 定义需要渲染的数据
    16             const result = await axios.get('xxxxxxxxxxxxxxxx')
    17             result.data.map(item=>{
    18                 // 数据处理(省略)
    19                 this.$refs.pie.init(temp)
    20             })
    21             // 渲染从 map.js 传过来的数据
    22             Bus.$on('AlarmInfoPie',(data)=>{
    23                 temp = data
    24             })
    25             this.$refs.pie.init(temp)
    26         },
    27          // 机器缺陷(图)
    28         async getRobotDefectPie(){
    29             let temp,   // 定义需要渲染的数据
    30             const result = await axios.get('xxxxxxxxxxxxxxxx')
    31             result.data.map(item=>{
    32                 // 数据处理(省略)
    33                 this.$refs.pie.init(temp)
    34             })
    35             // 渲染从 map.js 传过来的数据
    36             Bus.$on('defectPie',(data)=>{
    37                 temp = data
    38             })
    39             this.$refs.pie.init(temp)
    40         }
    41     },
    42 };

      一开始数据处理逻辑就是这样,结果却是:点击地图组件的某个区域时,会进行正常渲染 “机器告警” 的数据,如果点击 “机器缺陷” 时,再点击地图组件的当前区域时却得不到对应的数据,而是渲染的是 “机器告警” 的数据,当时很懵逼,最后才知道由于 右边视图组件共用了一个数据展示的组件,当点击地图某个区域时,map.js 中的 eventBus 会有两个事件发射,robotState.vue 中对应也就有两个事件监听,从而获取数据,无论是点击 “机器缺陷” 还是 “机器告警”,后面监听的事件得到的数据都会被覆盖。找到了问题原因就很好解决,最先想到的是使用 vuex 来解决,但是需要推翻以前的代码重写,因为项目中有很多数据展示,就很麻烦;然后想的是能不能使用 eventBus 中的方法来解决,最后找到了 eventBus.$off() 方法来解决。

      大致解决方法就是这样,可能解释的不是太清楚,自己可以写个案例实现下应该可以帮助理解。最后对 eventBus 的使用做一个小的补充,就是我们在项目中可能会创建多个 eventBus.js 文件,而两个或者多个组件要使用 eventBus 进行通信时一定要使用同一个 eventBus.js 文件,否则会报错,我之前就遇到过,哈哈!

      总结:Vue中使用 eventBus 实现组件间的通信时,需要对 Bus.$emit()Bus.$on()Bus.$off() 或者其他 API 搭配使用。结合当前环境,判断是否有干扰项从而决定是否对 eventBus 进行移除。

     

  • 相关阅读:
    Python集成开发环境搭建
    Windows10 解决 “/”应用程序中的服务器错误
    Windows系统清除远程连接记录的方法
    C# 处理DateTime算法,取某月第1天及最后一天
    SQL语句
    3389远程连接爆破实战
    SQL Server常用SQL集合
    VS2013、VS2015中,新建项目没有看到解决方案的问题(已解决)
    我的黑苹果装机篇
    C# 使用GZip对字符串压缩和解压
  • 原文地址:https://www.cnblogs.com/zsp-1064239893/p/13292029.html
Copyright © 2011-2022 走看看