Vue 進(jìn)階教程之:非父子組件通信方法(包含三個(gè)實(shí)際使用案例)

一提到兩個(gè)非父子組件通信方法,有經(jīng)驗(yàn)的 coder 肯定會(huì)說(shuō)用 Vuex 啊,我個(gè)人建議不要為了用 Vuex 而用 Vuex,除非你的項(xiàng)目很大,耦合度很高,需要大量的儲(chǔ)存一些 data,組件之間通信頻繁。當(dāng)然還是要根據(jù)自己的業(yè)務(wù)場(chǎng)景的來(lái)決定,總之還是那句話,不要為了用 Vuex 而用 Vuex!


Vue 官網(wǎng)介紹了非父子組件通信方法:

vue 官網(wǎng)

不過(guò)官網(wǎng)說(shuō)的太簡(jiǎn)單了,新手看完估計(jì)還是一臉懵逼。還有這個(gè)空的 Vue 實(shí)例放到哪里合適也值得商榷。
這篇文章的目的就是用一個(gè)簡(jiǎn)單的例子讓你明白如何用 Bus ?? 來(lái)進(jìn)行通信:

組件

請(qǐng)看上圖, bb 組件里面有個(gè)按鈕,點(diǎn)擊按鈕,把 123 傳遞給 aa 組件

// 根組件(this.$root)
new Vue({
  el: '#app',
  router,
  render: h => h(App),
  data: {
   // 空的實(shí)例放到根組件下,所有的子組件都能調(diào)用
    Bus: new Vue()
  }
})

bb 組件內(nèi)調(diào)用事件觸發(fā)↓

<button @click="submit">提交<button>

methods: {
   submit() {
     // 事件名字自定義,用不同的名字區(qū)別事件
      this.$root.Bus.$emit('eventName', 123)
    }
 }

aa 組件內(nèi)調(diào)用事件接收↓

  // 當(dāng)前實(shí)例創(chuàng)建完成就監(jiān)聽(tīng)這個(gè)事件
  created(){
    this.$root.Bus.$on('eventName', value => {
      console.log(value)
    })
  },
  
  methods: {
    print(value) {
      console.log(value)
    }
  },
  
  // 在組件銷毀時(shí)別忘了解除事件綁定
  beforeDestroy() {
     this.$root.Bus.$off('eventName')
  },

這樣就可以了,是不是很簡(jiǎn)單?


注意:在組件銷毀時(shí)要使用 $.off 取消資格綁定 ,不然 $.on 會(huì)觸發(fā)多次


問(wèn)題一:如果有多個(gè)組件組件需要通信,是不是要在根組件上多建幾個(gè) Bus?
答:不需要的,只要保證事件名 (eventName)不一樣就行了。

問(wèn)題二:為什么要弄個(gè) Bus?直接 this.$root.$on、this.$root.$emit 不更簡(jiǎn)單粗暴?

答:按照文檔上的說(shuō)法是專門用一個(gè)空的 Vue 實(shí)例(Bus)來(lái)做中央事件總線更加清晰也易于管理。


開(kāi)發(fā)環(huán)境中使用案例 一

  1. 新建一個(gè) eventHub.js
import Vue from 'vue'

export default new Vue()
  1. 在任意組件里拋出事件
import eventHub from '@/utils/eventHub'

export default {
   mounted() {
     eventHub.$emit('add', 'hello')
   }
}
  1. 在任意組件里接收事件
import eventHub from '@/utils/eventHub'

export default {
  created() {
    eventHub.$on('add', value => {
      console.log(param) // 'hello'
    })
 },
  destroyed () {
    eventHub.$off('add')
  }
}

開(kāi)發(fā)環(huán)境中使用案例 二

假設(shè)你用的是腳手架工具,引用文件名叫 main.js

import Vue from 'vue'
import App from './App'
 
//  全局組件之間通信
Vue.prototype.$eventHub= Vue.prototype.$eventHub ||  new Vue()        // 巴士
 
new Vue({
  el: '#app',
  template: '<App/>',
  components: {App},
  data: {
    eventHub: new Vue()
  }
})

組件部分

 <div class="hello">
    <h1 @click="go">傳遞</h1>
    <back></back>
  </div>
 
import back from "@/components/Background";
export default {
  methods: {
    go() {
      this.$eventHub.$emit("add-todo", "哈哈");
    }
  },
  components: {
    back
  }
};

引用組件

export default {
  created() {
    this.$eventHub.$on("add-todo", this.move);
    // 綁定接收回調(diào)過(guò)來(lái)的事件處理 
  },
  methods: {
    move(ab) {
      console.log("發(fā)送");
      console.log(ab);
    },
   // 別忘了 $.off ,這里省略不寫了
  }
};

開(kāi)發(fā)環(huán)境使用案例三

可以直接看 原文:Vue: EventHub 和 Vue 更配哦

EventHub 的主要功能就兩個(gè): 監(jiān)聽(tīng)和廣播,當(dāng)然還有去掉監(jiān)聽(tīng)器。

以上的案例沒(méi)有強(qiáng)調(diào)「廣播」,其實(shí)廣播功能也是很重要的。請(qǐng)看下面案例:

在頂層組件的 data 里初始化 EventHub,并使用 provide 對(duì)外暴露這個(gè) EventHub

export default {
  name: "App",
  components: {
    GrandParent
  },
  data() {
    return {
      eventHub: new Vue()
    };
  },
  provide() {
    return {
      eventHub: this.eventHub
    };
  },
  methods: {
    setRandomValue() {
      this.eventHub.$emit("update:msg", Math.random() * 100);
    }
  }
};

然后在需要監(jiān)聽(tīng)的組件里用 inject 注入這個(gè)依賴,并在 created 里添加事件監(jiān)聽(tīng)

export default {
  inject: ["eventHub"],
  data() {
    return {
      msg: ""
    };
  },
  created() {
    this.eventHub.$on("update:msg", msg => {
      this.msg = msg;
    });
  },
 // 別忘了 $.off,這里省略不寫
};

最終的結(jié)果是在 App 里修改 msg,添加監(jiān)聽(tīng)事件的子組件都會(huì)獲取最新的 msg,并用其再更新自己的數(shù)據(jù)或者狀態(tài)。
(父組件拋出事件,添加監(jiān)聽(tīng)事件的子組件都會(huì)觸發(fā),這不就是廣播嘛)


部分代碼引用鏈接
https://blog.csdn.net/dexing07/article/details/82631252
http://www.itdecent.cn/p/40127e3d9905


文中如有錯(cuò)誤,歡迎在評(píng)論中指出,謝謝。
碼字辛苦,文章如對(duì)您有幫助,麻煩支持點(diǎn)贊~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容