Vue如何實現(xiàn)組件間通信
1. 父子間通信
最常見的就是父子之間的通信,通信是雙向的數(shù)據(jù)傳遞。
1.1 父組件 --> 兒子組件
父組件向兒子組件傳遞數(shù)據(jù)的方式就是 通過 Prop 向子組件傳遞數(shù)據(jù)。
//child.vue <template> <div> 我是兒子,我收到來自父親的數(shù)據(jù)為 {{value}} </div> </template> <script> export default { props:{ value: String } }
//App.vue <template> <div id="app"> <Child :value="x" /> </div> </template> <script> import Child from './components/Child' export default { data(){ return { x: 'hi,child' } }, components:{ Child } } </script>
1.2 兒子組件 --> 父組件
兒子組件向父組件傳遞數(shù)據(jù)的方式就是通過子組件內(nèi) $emit 觸發(fā)自定義事件,子組件使用時 v-on 綁定監(jiān)聽自定義事件。
這里的 v-on 事件通信是在子組件使用時作為子組件的事件屬性自動進行監(jiān)聽的。
因此兒子組件向父組件傳遞數(shù)據(jù),依賴于子組件使用時的自定義事件屬性。
//child.vue <template> <div> 我是兒子,我收到來自父親的數(shù)據(jù)為 {{value}} <button @click="sayHi"> 向父組件打招呼 </button> </div> </template> <script> export default { props:{ value: String }, methods:{ sayHi(){ this.$emit('sayHi','hi,parent!'); } } } </script>
//App.vue <template> <div id="app"> 我是父組件,我收到子組件傳來的數(shù)據(jù)為 {{y}} <Child :value="x" @sayHi="y = $event"/> </div> </template> <script> import Child from './components/Child' export default { data(){ return { x: 'hi,child', y: '' } }, components:{ Child } } </script>
2. 爺孫間通信
爺孫間通信,可以使用兩次 v-on 通信,爺爺爸爸通信,然后爸爸兒子通信。
也可使用下方的任意組件間通信的方式。
3. 任意組件間通信
任意組件間通信就不再區(qū)分是 A 向 B 通信,還是 B 向 A 通信,而是通用的方式,誰想發(fā)送數(shù)據(jù)就使用對應(yīng)的 API 發(fā)送數(shù)據(jù),誰想要接收什么數(shù)據(jù),就使用對應(yīng)的 API 接收。
任意組件間通信有兩種方式,一種是使用 EventBus 發(fā)布訂閱模式通信,一種是使用 Vuex 通信。
3.1 EventBus
EventBus ,從字面意思理解就是事件公交車,所有觸發(fā)的事件傳遞的數(shù)據(jù)都從前門上車保存到公交車上,然后通過監(jiān)聽對應(yīng)事件提供的出口讓對應(yīng)的事件數(shù)據(jù)下車。
EventBus,實際意思是發(fā)布和訂閱模式,就是誰想把數(shù)據(jù)傳遞出去,就要通過觸發(fā)自定義事件的 API 進行數(shù)據(jù)的發(fā)布;誰需要接收該數(shù)據(jù)信息的,就通過事件監(jiān)聽的 API 進行數(shù)據(jù)的監(jiān)聽,一旦檢測到監(jiān)聽的數(shù)據(jù)發(fā)布出來,就會接收,這就是數(shù)據(jù)的訂閱。
EventBus 通信方式最重要是搞明白發(fā)布和訂閱的接口 API,在 Vue 中,Vue 實例有提供兩個接口,即 $emit
和 $on
,因此可以新創(chuàng)建一個空的 Vue 實例,來獲得這兩個接口。
const eventBus = new Vue(); eventBus.$emit(eventName, […args]) //發(fā)布事件 eventBus.$on(event, callback) //訂閱事件
實例如下:
// eventBus.js import Vue from 'vue' export const eventBus = new Vue();
//child <template> <div> 我是兒子,我收到來自父親的數(shù)據(jù)為 <strong>{{value}}</strong> <button @click="sayHi"> 向父組件打招呼 </button> <button @click="sibling"> 向兄弟組件打招呼 </button> </div> </template> <script> import {eventBus} from '../eventBus.js' export default { props:{ value: String }, methods:{ sayHi(){ this.$emit('sayHi','hi,parent!'); }, sibling(){ eventBus.$emit('sibling','hi,brother'); } } } </script> <style scoped> strong{ color: red; } </style>
//sibling <template> <div> 我是兄弟組件,我收到來自兒子組件的數(shù)據(jù)信息為 <strong>{{x}}</strong> </div> </template> <script> import {eventBus} from '../eventBus.js' export default { data(){ return { x: '' } }, mounted(){ eventBus.$on('sibling', (msg)=>{ this.x = msg; }) } } </script> <style scoped> strong{ color: green; } </style>
//parent <template> <div id="app"> 我是父組件,我收到子組件傳來的數(shù)據(jù)為 <strong>{{y}}</strong> <Child :value="x" @sayHi="y = $event"/> <Sibling></Sibling> </div> </template> <script> import Child from './components/Child' import Sibling from './components/Sibling' export default { data(){ return { x: 'hi,child', y: '' } }, components:{ Child, Sibling } } </script> <style scoped> strong{ color: blue; } </style>
關(guān)于 EventBus 這部分,可能存在這樣一個疑問,既然 Vue 實例中都有 $emit 和 $on,為什么不直接用 this.$emit 觸發(fā)事件, this.$on 接收事件呢?還非得要額外一個空實例 eventBus = new Vue() 。那是因為,Vue 中每個組件都是一個單獨的 Vue 實例,你在這個 Vue 實例中觸發(fā)該實例的 emit 事件,另外一個實例的 on 事件是接收不到的,不在一輛公交車上,怎么能進行事件通信呢?因此就必須要一個公共的公交車,也就是事件總線。
上述實例中的 eventBus 的使用方法是局部的 eventBus,誰要用到 eventBus 要自己手動引入。也可以將 eventBus 做成全局的,比如掛在 vue 的原型上。
//main.js import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false Vue.prototype.$eventBus = new Vue();//添加這句,一定要在下方的 new Vue 前。 new Vue({ render: h => h(App), }).$mount('#app')
//child sibling(){ this.$eventBus.$emit('sibling','hi,brother'); }
//sibling mounted(){ this.$eventBus.$on('sibling', (msg)=>{ this.x = msg; }) }
除了上述的添加屬性到 Vue 原型的方式外,還可以使用 Object.defineProperty() 為 Vue 原型添加屬性。
import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false let eventBus = new Vue() Object.defineProperty(Vue.prototype,'$eventBus',{ get(){ return eventBus } }) new Vue({ render: h => h(App), }).$mount('#app')
3.2 Vuex
Vue 組件間的通信也可使用專門為 vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式:Vuex。Vuex 的使用比較復(fù)雜,詳細(xì)可見 Vuex 博客。Vuex 適用于大型的復(fù)雜的 Vue 項目的狀態(tài)管理。對于一些中小型的應(yīng)用程序,可以根據(jù) Vuex 的原理自定義 store 模式進行狀態(tài)管理,vue 自定義狀態(tài)管理,可詳見 Vue 簡單狀態(tài)管理—store模式 博客。
無論是 Vuex 還是 自定義 store模式 ,其實現(xiàn)組件間通信的原理都是通過共享數(shù)據(jù)的方式實現(xiàn)的。組件間使用相同的數(shù)據(jù)源,當(dāng)一個組件改變數(shù)據(jù)時,另一個組件依賴的數(shù)據(jù)源也就改變了。
以上就是Vue如何實現(xiàn)組件間通信的詳細(xì)內(nèi)容,更多關(guān)于Vue組件間通信的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue點擊按鈕動態(tài)創(chuàng)建與刪除組件功能
這篇文章主要介紹了vue點擊按鈕動態(tài)創(chuàng)建與刪除組件功能,本文通過實例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12Vue下滾動到頁面底部無限加載數(shù)據(jù)的示例代碼
本篇文章主要介紹了Vue下滾動到頁面底部無限加載數(shù)據(jù)的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-04-04Element InputNumber 計數(shù)器的實現(xiàn)示例
這篇文章主要介紹了Element InputNumber 計數(shù)器的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08