鍍金池/ 問答/網(wǎng)絡安全  HTML/ vue bus 多次觸發(fā),使用bus.$off()報錯

vue bus 多次觸發(fā),使用bus.$off()報錯

問題描述

1,一個頁面中引入了兩個兄弟組件,show-relation和echart-line,通過bus來傳遞值和事件通信,
首先:show-relation中有個input,輸入一個詞,onblur事件來發(fā)送請求,服務端返回一組數(shù)據(jù),通過bus.$emit("sendData", arr)傳遞給echart-line組件
然后:echart-line是用的echarts圖表顯示數(shù)據(jù),點擊其中一個詞,把詞再傳遞給show-realtion組件,調用方法發(fā)送請求,服務端再次返回相關數(shù)據(jù).再重復之前過程

問題出現(xiàn)的環(huán)境背景及自己嘗試過哪些方法

我使用的eventBus來進行的通信

相關代碼

// 請把代碼文本粘貼到下方(請勿用圖片代替代碼)
//vue-happy-bus.js

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

// 記錄所有的事件類型與事件函數(shù)
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)//把服務端返回的數(shù)據(jù)傳遞給另外一個組件
          }
        })
        .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 = { //創(chuàng)建周圍近義詞的對象
                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', //節(jié)點的形狀'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow'
                symbolSize: 50, //節(jié)點的大小
                roam: true, //是否可以鼠標拖拽
                edgeSymbol: ['circle', 'arrow'], //可以指定為箭頭
                edgeSymbolSize: [4, 10],
                // focusNodeAdjacency: true, //在鼠標移動到節(jié)點上時顯示鄰接節(jié)點和連線
                // repulsion: 8000, //節(jié)點之間的斥力
                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('觸發(fā)了一次')
          BusFactory.$emit('changeCenter', name)
          BusFactory.$off('changeCenter')

        });

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

你期待的結果是什么?實際看到的錯誤信息又是什么?

clipboard.png

clipboard.png
之前因為沒有用BusFactory.$off()銷毀bus事件,出現(xiàn)成倍重復的情況,這里的使用.off銷毀的時候報錯,求大神解惑,其中的bus.js是參考網(wǎng)上大神寫的,如有侵權請直接聯(lián)系我

回答
編輯回答
凝雅

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

2017年12月29日 23:32