超詳細(xì)的vue組件間通信總結(jié)
前言
組件通信在我們平時(shí)開發(fā)過程中,特別是在vue和在react中,有著舉足輕重的地位。本篇將總結(jié)在vue中,組件之間通信的幾種方式:
- props、$emit
- $parent、$children
- $attrs、$listeners
- provide、inject
- eventBus
- vuex
- 本地存儲(chǔ)
一、props、$emit單向數(shù)據(jù)流

father.vue:
<template>
<div>
<div>我是父親:<input type="button" value="父親" /> 數(shù)字為: {{num}}</div>
<son :num="num" @change="change"></son>
</div>
</template>
<script>
import son from "./son.vue";
export default {
name: "Father",
components: {
son,
},
data() {
return {
num: 1,
};
},
methods:{
change(val){
this.num = val
}
}
};
</script>
son.vue:
<template>
<div>我是兒子:<input type="button" value="兒子" @click="change"/>數(shù)字為:{{num}}</div>
</template>
<script>
export default {
name: "App",
components: {},
props: {
num: {
default: 0,
},
},
created() {},
methods: {
change(){
// this.num = 2 props通信是單向數(shù)據(jù)流,在這直接修改父組件傳過來的num將會(huì)報(bào)錯(cuò) // 可以用$emit觸發(fā)change事件,father組件綁定change事件 this.$emit('change', 2)
}
},
};
</script>

對(duì)于上面的場(chǎng)景:子組件的change事件只是為了修改父組件中某一個(gè)值,還可以有以下幾種寫法:
1.父組件綁定給子組件的事件使用箭頭函數(shù)
father:
<son :num="num" @change="val => num = val"></son>
son:
this.$emit('change', 2)
2.update:num和.sync
father:
<son :num.sync="num"></son>
son:
this.$emit('update:num', 2)//update是規(guī)定的寫法,不可更換
3.v-model
先修改props和綁定的事件:
father:<son :value="num" @input="val => num = val"></son>son:this.$emit('input', 2)
可用v-model簡(jiǎn)寫:<son v-model="num"></son>
二、$parent、$children
$parent、$children可直接在父子組件中調(diào)用各自的方法以及修改數(shù)據(jù)
子組件中直接:this.$parent.num = 2
父組件中$children是個(gè)數(shù)組,因此具體是哪個(gè)子組件不太直觀,可以用$refs來操作子組件
vue官方并不推薦使用這種通信方式:節(jié)制地使用$parent和$children- 它們的主要目的是作為訪問組件的應(yīng)急方法,更推薦用 props 和 events 實(shí)現(xiàn)父子組件通信。
三、$attrs、$listeners
$attrs可以拿到父組件傳過來的屬性:
<div>我是兒子:<input type="button" value="兒子" @click="change"/>數(shù)字為:{{$attrs}}</div>

dom節(jié)點(diǎn):

$attrs會(huì)直接將傳過來的屬性放到對(duì)應(yīng)的標(biāo)簽上,反觀props就不會(huì)。如果想去掉標(biāo)簽中的這些屬性,可以用inheritAttrs:

值得注意的是:props的優(yōu)先級(jí)大于$attrs,即當(dāng)props存在的時(shí)候,$attrs為空對(duì)象:

$attrs常用于跨多級(jí)組件傳遞屬性,比如祖孫組件,用父組件做中轉(zhuǎn):
father:
<son v-bind="$attrs"></son>
$attrs用于屬性跨級(jí)傳遞,方法跨級(jí)傳遞則用$listeners。
grandFather.vue:
<template>
<div>
<div>我是祖父: 數(shù)字為:{{nums}}</div>
<father :nums="nums" @up="up" @down="down"></father>
</div>
</template>
<script>
import father from "./father.vue";
export default {
name: "App",
components: {
father,
},
data(){
return {
nums:0
}
},
methods: {
up() {
alert('up')
}, down() { alert('down') },
},
};
</script>
father.vue:
<son v-bind="$attrs" v-on="$listeners"></son>
son.vue:
<div>我是兒子:<input type="button" value="兒子" @click="$listeners.up"/></div>

四、provide、inject
這對(duì)選項(xiàng)需要一起使用,以允許一個(gè)祖先組件向其所有子孫后代注入一個(gè)依賴,不論組件層次有多深,并在其上下游關(guān)系成立的時(shí)間里始終生效
provide選項(xiàng)應(yīng)該是一個(gè)對(duì)象或返回一個(gè)對(duì)象的函數(shù)。
inject選項(xiàng)應(yīng)該是一個(gè)字符串?dāng)?shù)組或一個(gè)對(duì)象。
App:
...
export default {
provide(){
return {vm: this}
},
...
son:
...
export default {
inject: ['vm'], data(){}, mounted(){ console.log(this.vm) }
...

注意:provide 和 inject 綁定并不是可響應(yīng)的。這是刻意為之的。然而,如果你傳入了一個(gè)可監(jiān)聽的對(duì)象,那么其對(duì)象的 property 還是可響應(yīng)的。
inject注入中的值會(huì)沿著組件向上查找,遵從"就近原則"。
provide 和 inject中的數(shù)據(jù)流是雙向的。
五、eventBus(事件總線)
eventBus通過發(fā)布訂閱全局事件,供其他組件使用。
在main.js中:
Vue.prototype.$bus = new Vue();
parent.vue:
<template>
<div>
<son1></son1>
<son2></son2>
</div>
</template>
<script>
import son1 from './son1.vue'
import son2 from './son2.vue'
export default {
name: 'parent',
components: {
son1,
son2
},
created(){
this.$bus.$on('busEvent',(v)=>{
console.log(v);
})
},
beforeDestroy(){
this.$bus.off('busEvent')
}
}
</script>
son1和son2中的mounted:
son1:mounted(){
this.$bus.$emit('busEvent','son1哈哈')
}son2:mounted(){ this.$bus.$emit('busEvent', 'son2嘻嘻')}
打印結(jié)果:

使用eventBus有三點(diǎn)需要注意,1.$bus.on應(yīng)該在created鉤子內(nèi)使用,如果在mounted使用,它可能接收不到其他組件來自created鉤子內(nèi)發(fā)出的事件;
2.$bus.emit應(yīng)該在mounted中使用,等待created中的$bus.on事件綁定完成;
3.發(fā)布訂閱的事件在beforeDestory鉤子里需要使用$bus.off解除,組件銷毀后沒必要一直監(jiān)聽。
六、vuex
借助vuex的狀態(tài)管理來實(shí)現(xiàn)組件通信,vuex適用于較為復(fù)雜的項(xiàng)目,頻繁的數(shù)據(jù)共享且數(shù)據(jù)量比較大。
store/index.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
isLogin: false
},
mutations: {
loginState (state, isLogin) {
state.isLogin = isLogin
}
}
})
export default store
App.vue:
created(){
this.$store.commit('loginState',true)// 設(shè)置登錄狀態(tài)為true
},
son.vue:
<template>
<div>我是兒子:<input type="button" value="兒子" />登錄狀態(tài):{{isLogin}}</div>
</template>
<script>
import {mapState} from 'vuex';
export default {
name: "son",
computed:{
...mapState(['isLogin'])
}
};
</script>

七、localstorage
localstorage是瀏覽器的本地存儲(chǔ),將會(huì)長(zhǎng)期存儲(chǔ)在瀏覽器中,非常龐大的數(shù)據(jù)不建議用此方式。
App.vue
created(){
localStorage.setItem('isLogin', true)
},
son.vue:
computed:{
isLogin(){
return localStorage.getItem('isLogin')
}
}
常見的組件通信方式基本就是這些啦,有什么遺漏或不足的,歡迎評(píng)論區(qū)留言!
總結(jié)
到此這篇關(guān)于vue組件間通信的文章就介紹到這了,更多相關(guān)vue組件間通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue+vant移動(dòng)端顯示table表格加橫向滾動(dòng)條效果
vant移動(dòng)端顯示table效果,增加復(fù)選框,可以進(jìn)行多選和全選,加橫向滾動(dòng)條,可以看全部?jī)?nèi)容,下面通過本文給大家分享vue+vant移動(dòng)端顯示table表格加橫向滾動(dòng)條效果,感興趣的朋友跟隨小編一起看看吧2024-06-06
vue.js單頁面應(yīng)用實(shí)例的簡(jiǎn)單實(shí)現(xiàn)
本篇文章主要介紹了vue.js單頁面應(yīng)用實(shí)例的簡(jiǎn)單實(shí)現(xiàn),使用單頁應(yīng)用,沒有頁面切換,就沒有白屏阻塞,可以大大提高 H5 的性能,達(dá)到接近原生的流暢體驗(yàn)。2017-04-04
el-menu如何根據(jù)多層樹形結(jié)構(gòu)遞歸遍歷展示菜單欄
這篇文章主要介紹了el-menu根據(jù)多層樹形結(jié)構(gòu)遞歸遍歷展示菜單欄,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-07-07
vuex?mutation?action同級(jí)調(diào)用方式
這篇文章主要介紹了vuex?mutation?action同級(jí)調(diào)用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
在vue中動(dòng)態(tài)添加class類進(jìn)行顯示隱藏實(shí)例
今天小編就為大家分享一篇在vue中動(dòng)態(tài)添加class類進(jìn)行顯示隱藏實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-11-11
vue項(xiàng)目百度地圖如何自定義標(biāo)注marker
這篇文章主要介紹了vue項(xiàng)目百度地圖如何自定義標(biāo)注marker問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03

