tony
  • 2
  • 新人请关照

vue bus 多次触发,使用bus.$off()报错

问题描述

1,一个页面中引入了两个兄弟组件,show-relation和echart-line,通过bus来传递值和事件通信,
首先:show-relation中有个input,输入一个词,onblur事件来发送请求,服务端返回一组数据,通过bus.$emit("sendData", arr)传递给echart-line组件
然后:echart-line是用的echarts图表显示数据,点击其中一个词,把词再传递给show-realtion组件,调用方法发送请求,服务端再次返回相关数据.再重复之前过程

问题出现的环境背景及自己尝试过哪些方法

我使用的eventBus来进行的通信

相关代码

// 请把代码文本粘贴到下方(请勿用图片代替代码)
//vue-happy-bus.js

import Vue$ from 'vue'
let Vue = Vue$
if (typeof window !== 'undefined' && window.Vue) {
    Vue = window.Vue
}

// 记录所有的事件类型与事件函数
const EventStore = {}
const Bus = new Vue()

// 移除所有事件的方法
const destroyHandler = function() {
    // this 为调用此方法的vue组件
    const currentEventObj = EventStore[this._uid]
    if (typeof currentEventObj === 'undefined') {
        return
    }
    for (let type in currentEventObj) {
        const key = Array.isArray(type) ? type.join(',') : type
            // Bus 解绑事件
        Bus.$off(type, currentEventObj[key])
    }
    // 删除记录的事件集合
    delete EventStore[this._uid]
}

const BusFactory = vm => {
    // 当前调用组件的 destroyed 钩子
    const destroyed = vm.$options.destroyed
        // 当前组件的唯一标示(vue生成的自增ID)
    const uid = vm._uid
        // 初始化当前组件的事件集合对象
    EventStore[uid] = {}
        // 为当前组件挂载destroyed钩子
        !destroyed.includes(destroyHandler) && destroyed.push(destroyHandler)

    return {
        $on: (type, handler) => {
            const key = Array.isArray(type) ? type.join(',') : type
            EventStore[uid][key] = handler
            Bus.$on(type, handler)
        },
        $off: (type, handler) => {
            // $off() 时 type 为空,移除所有事件
            if (!type) {
                // 删除该uid下事件集合
                delete EventStore[uid]
                Bus.$off()
                return
            }
            const key = Array.isArray(type) ? type.join(',') : type
                // 删除对应的事件
            delete EventStore[uid][key]
            Bus.$off(type, handler)
        },
        $once: (...params) => Bus.$once(...params),
        $emit: (...params) => Bus.$emit(...params)
    }
}

BusFactory.$emit = (...params) => Bus.$emit(...params)
BusFactory.$once = (...params) => Bus.$once(...params)

export default BusFactory

//show-relation.vue

<input  @blur="getSerValue(value)" v-model="value" :placeholder="expValue.msg" />
import axios from 'axios'
import BusFactory  from '@/util/vue-happy-bus'
data() {
    return {
      Bus: BusFactory(this),// 使用BusFactory�将this绑定之后,返回一个 bus,即可无需关心销毁的问题了
      res:'',                     //后端处理后返回的值
      value: '',                  //textarea的值
      }
},
mounted() {
    this.Bus.$on('changeCenter', v => {
      console.log('接收了一次')
      this.value =v
      this.getSerValue(v)
    })
  },
  beforeDestroy() {
    console.log('show-relation销毁前');
    Bus.$off('changeCenter')
  },
  methods: {
    getSerValue(val) {
      let me = this;
      if(val){
        me.Bus.$emit('sendInputValue', val)
        axios.get(me.expValue.tradeUrl)
        .then(function (response) {
          me.res = response.data.body;
          if(me.res){
            me.Bus.$emit('sendData', me.res)//把服务端返回的数据传递给另外一个组件
          }
        })
        .catch(function (error){
          me.newValue = error;
        });
      }else{
        me.expValue.msg = '您输入为空, 无法解析空值!';
      }
    }
  }

//echart-line.vue

<div class="echart-line">
    <div class="box">
      <div class="main" ref="main"></div>
    </div>
  </div>
</template>
<script>
import echarts from 'echarts'
import BusFactory from '@/util/vue-happy-bus'
export default {
  name: 'echart-line',
  data() {
    return {
      Bus: BusFactory(this),// 使用BusFactory�将this绑定之后,返回一个 bus,即可无需关心销毁的问题了
      inputValue: ''
    }
  },
  mounted() {
    let me = this;
    me.Bus.$on('sendData', v => {
      me.drawPic(v)
    });
    me.Bus.$on('sendInputValue', v=>{
      me.inputValue = v;
      console.log(v);
    })
  },

  methods: {
    drawPic(dataArray) {
      let me = this;
      let personArr = [];
      let linksArr = [];
      let dataObjs = [];//存放图表的data 词对象
      let linkObjs = [];//存放图表的links 关系
      dataArray.forEach(v => {
        if(v.name != me.inputValue){
          personArr.push(v.name);
          linksArr.push(v.value);
        }
      });
      let centerData = {//中心的对象
        name: me.inputValue,
        symbolSize: 100,
        itemStyle: {
            normal: {
                color: 'blue'
            }
        }
      };
      dataObjs.push(centerData);//把中心的对象先放到data里面
      personArr.forEach(v => {
        let dataObj = { //创建周围近义词的对象
                name: v,
                symbolSize: 50,
                itemStyle: {
                    normal: {
                        color: 'green'
                    }
                }
            };
        dataObjs.push(dataObj);
      });

      linksArr.forEach(n=>{
          dataArray.forEach(m=>{
            if(n === m.value){
              let linkObj = {
                    source: m.name,
                    target: this.inputValue,
                    name: n,
                    lineStyle: {
                        normal: {
                            type: 'dotted',
                            color: 'blue'
                        }
                  }
              }
              linkObjs.push(linkObj)
            }
          })
      })
      console.log(dataObjs)
      console.log(linkObjs)

      //初始化
      let myChart = echarts.init(this.$refs.main);
        let option = {

            title: {
                text: '任务关系图'
            },
            tooltip: {
                formatter: function(x) {
                    return x.data.des;
                }
            },
            series: [{
                type: 'graph', //图形类型
                layout: 'force',
                symbol: 'circle', //节点的形状'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow'
                symbolSize: 50, //节点的大小
                roam: true, //是否可以鼠标拖拽
                edgeSymbol: ['circle', 'arrow'], //可以指定为箭头
                edgeSymbolSize: [4, 10],
                // focusNodeAdjacency: true, //在鼠标移动到节点上时显示邻接节点和连线
                // repulsion: 8000, //节点之间的斥力
                edgeLabel: {
                    normal: {
                        textStyle: {
                            fontSize: 10,
                            backgroundColor: '#fff'
                        }
                    }
                },
                force: {
                    repulsion: 1500,
                    edgeLength: [10, 100]
                },
                draggable: false,
                itemStyle: {
                    normal: {
                        color: 'blue',

                    }
                },
                lineStyle: {
                    normal: {
                        width: 2,
                        color: 'blue'

                    }
                },
                edgeLabel: {
                    normal: {
                        show: false,
                        formatter: function(x) {
                            return x.data.name;
                        }
                    }
                },
                label: {
                    normal: {
                        show: true,
                        textStyle: {}
                    }
                },
                 data: dataObjs,

          links: linkObjs,

            }]
        };
        myChart.setOption(option);
        myChart.on('click', function(params) {
          let me = this;
          let name = params.name;
          console.log('触发了一次')
          BusFactory.$emit('changeCenter', name)
          BusFactory.$off('changeCenter')

        });

    }
  },
beforeUpdate() {
 bus.$off()
  },
}
</script>

你期待的结果是什么?实际看到的错误信息又是什么?

clipboard.png

clipboard.png
之前因为没有用BusFactory.$off()销毁bus事件,出现成倍重复的情况,这里的使用.off销毁的时候报错,求大神解惑,其中的bus.js是参考网上大神写的,如有侵权请直接联系我

阅读 2.6k
评论 更新于 2018-07-15
    1 个回答
    evaz
    • 227

    大哥
    你忘了加this.Bus.$off

    评论 赞赏 2018-07-16
      撰写回答

      登录后参与交流、获取后续更新提醒