Vue如何解決兄弟組件之間傳值問(wèn)題
解決兄弟組件之間傳值問(wèn)題
vue中 父組件向子組件傳遞參數(shù)時(shí),可以通過(guò)prop來(lái)傳遞參數(shù),prop可以是數(shù)組形式,也可以是對(duì)象格式,子向父組件傳遞參數(shù)時(shí),通過(guò)$emit來(lái)傳遞,$emit('方法名', 傳參),來(lái)實(shí)現(xiàn)子組件和父組件數(shù)據(jù)交互,但是在父組件中,有好多個(gè)子組件,這些子組件怎么樣來(lái)進(jìn)行數(shù)據(jù)通訊呢?
有的同學(xué)會(huì)立馬想到 vuex ,答案是:可以的,但是會(huì)不會(huì)大材小用?在項(xiàng)目中,只是個(gè)別組件需要用到通訊,我們是不會(huì)優(yōu)先考慮vuex來(lái)解決的。
下面我們可以使用一個(gè)特別好用的方法來(lái)實(shí)現(xiàn)兄弟組件之間數(shù)據(jù)通訊
bus.js 顧名思義 巴士,所有人都可以上車,不管你在哪里,不管你是什么組件,我都可以開(kāi)車過(guò)去接你。
bus可以通過(guò)兩種方式來(lái)實(shí)現(xiàn)
1. 通過(guò)創(chuàng)建.js文件局部方式來(lái)實(shí)現(xiàn),在需要用到的組件中引入,然后調(diào)用它即可
在項(xiàng)目的utils文件中創(chuàng)建一個(gè)js文件,在正常的項(xiàng)目種,會(huì)用utils來(lái)存放哪些共用的js文件,這些js文件是一些常用的方法或例如這個(gè)bus
// bus.js import Vue from 'vue'; export default new Vue();
接下來(lái),哪個(gè)組件需要發(fā)車你就在哪里import給它建立一個(gè)發(fā)車點(diǎn)
// 在 vue組件中引入 import bus from "../../utils/bus";
然后這里我們?cè)趘ue的實(shí)例中的methods函數(shù)中定義一個(gè)方法來(lái)觸發(fā)這個(gè)bus發(fā)車
methods: { ? ? ? busFun(data) { ? ? ? ? // 通過(guò) $emit 來(lái)觸發(fā)方法,參數(shù)1 是定義方法名,參數(shù)2 是你要發(fā)送的數(shù)據(jù) ? ? ? ? bus.$emit('name', data) ? ? ? }, ? ? }
這里千萬(wàn)要注意了,若你使用多個(gè)bus 那么參數(shù)1命名千萬(wàn)別重復(fù),否則其他組件會(huì)出現(xiàn)無(wú)故上車的情況,這個(gè)bus中可以給無(wú)數(shù)個(gè)組件使用,但是命名不能重復(fù),除非你創(chuàng)建多個(gè)bus。
接下來(lái)我們就看看這輛巴士有哪個(gè)組件要上車。
同樣,如果其他組件要上車,我們必須要在這個(gè)組件中設(shè)立一個(gè)車站,不然巴士不知道要在哪里接這個(gè)組件。
// 這個(gè)組件需要上車,我們先設(shè)立一個(gè)車站 import bus from "../../utils/bus";
設(shè)立車站后,我們就需要通過(guò) bus.$on來(lái)觸發(fā),也就是上車的技能
?created() { ? ? ? bus.$on('name', (data) => { ? ? ? ? console.log(data, '上車成功'); ? ? ? }) ? ? }, ? ? // 打卡 ? ? beforeDestroy() { ? ? ? bus.$off('name'); ? ? },
這里會(huì)有同學(xué)會(huì)疑惑,為什么上車后需要打卡???
我們先說(shuō)從上往下說(shuō)吧,首先我們必須要在 vue 的created鉤子函數(shù)中來(lái)觸發(fā)這個(gè)bus,在頁(yè)面還沒(méi)加載的時(shí)候我們先觸發(fā)它然后拿到數(shù)據(jù),在created中執(zhí)行,我們可以避免很多坑,例如觸發(fā)bus無(wú)法拿到數(shù)據(jù)等問(wèn)題(想了解的同學(xué)去問(wèn)度娘,這里就不說(shuō)明了)。
然后我們每次觸發(fā)這個(gè)bus的時(shí)候,我們必須在整個(gè)生命周期走完的時(shí)候?qū)⑦@個(gè)bus給移除掉。
簡(jiǎn)單粗暴的說(shuō),就是我們每個(gè)組件上車的時(shí)候,我們必須要給它打卡掉,讓后面的bus知道這個(gè)組件已經(jīng)上車了,不需要在這里等待,接到就開(kāi)走,頭都不回的那種。
執(zhí)行beforeDestroy來(lái)銷毀這個(gè)bus方法,是避免方法“冗余”,若不清除這個(gè)方法,那將會(huì)出現(xiàn)多個(gè)bus觸發(fā),每次都會(huì)將這輛bus停留在這個(gè)vue的生命周期中,打開(kāi)控制臺(tái)你會(huì)發(fā)現(xiàn)有好多輛bus在這里停留,因?yàn)槲覀兠看斡|發(fā)bus時(shí),就會(huì)開(kāi)一輛巴士出來(lái),而不是這輛巴士一直重復(fù)開(kāi)的原因。
2. 接下來(lái)我們就說(shuō)一下第二種方式
// 我們?cè)趍ain.js中用常量創(chuàng)建一個(gè)bus,然后將它放入Vue實(shí)例的原型對(duì)象中。 const bus = new Vue() Vue.prototype.$bus = bus;
然后我們就可以在全局 通過(guò)this.$bus來(lái)開(kāi)巴士了(#滑稽)。接下來(lái)只要開(kāi)穩(wěn)就可以為所欲為了。
?created() { ? ? ? this.$bus.$on('name', (data) => { ? ? ? ? console.log(data, '上車成功'); ? ? ? }) ? ? }, ? ? // 打卡 ? ? beforeDestroy() { ? ? ? this.$bus.$off('name'); ? ? },
最后別忘了給乘客打卡哦!
各類組件間傳值方法(父子、兄弟、頁(yè)級(jí))
熟悉vue各類關(guān)系的組件之間傳值方法會(huì)令開(kāi)發(fā)更加得心應(yīng)手,下面將對(duì)父子、兄弟、頁(yè)級(jí)組件之間的傳值作淺談。
父子關(guān)系組件
- 父向子組件傳值
父組件向子組件傳值通常是利用props屬性。首先,在子組件里定義一個(gè)props值用來(lái)接收父組件數(shù)據(jù);然后調(diào)用子組件并v-bind綁定這個(gè)props值 = 父組件的data值。
父組件代碼:
<template> ? <div class="home"> ? ? <HelloWorld :newMsg="msg" />? ? ? //綁定子組件newMsg(props值) = 父組件msg(data值) ? </div> </template>
<script> import HelloWorld from "@/components/HelloWorld.vue"; export default { ? name: "Home", ? data(){ ? ? return{msg:'Welcome to Vue.js'} //父組件數(shù)據(jù)msg ? }, ? components: {HelloWorld} }; </script>
子組件代碼:
<template> ? <div> ? ? <h1>{{ newMsg }}</h1> ?//直接調(diào)用newMsg,顯示“Welcome to Vue.js” ? </div> </template>
<script> export default { ? name: "HelloWorld", ? props: {newMsg: String} ?//為子組件定義newMsg(props值)接收父組件msg ? //或者props:['newMsg'] }; </script>
- 子向父組件傳值
子組件向父組件傳值有兩種方式:
1. 利用$emit()方法。 首先在子組件中用$emit()向上傳遞一個(gè)自定義事件并附帶想要傳遞的數(shù)據(jù);然后在父組件v-on監(jiān)聽(tīng)這個(gè)自定義事件并自動(dòng)接收到數(shù)據(jù);最后在響應(yīng)該事件的方法中進(jìn)行數(shù)據(jù)操作。
子組件代碼:
<script> export default { ? name: "HelloWorld", ? data() { ? ? return {msg:"Welcome to Vue"} //data值,即將向上傳遞的值 ? }, ? created(){ ? ? this.$emit('change',this.msg) //向上傳遞自定義事件change和data值。這里我調(diào)用created生命周期函數(shù)觸發(fā)$emit() ? } }; </script>
父組件代碼:
<template> ? <div class="home"> ? ? <HelloWorld @change="handle" /> //監(jiān)聽(tīng)到子組件傳遞來(lái)的事件并響應(yīng)handle方法 ? ? <span>{{newMsg}}</span> ?//直接調(diào)用newMsg,顯示“Welcome to Vue” ? </div> </template>
<script> import HelloWorld from "@/components/HelloWorld.vue"; export default { ? name: "Home", ? data() { ? ? return {newMsg:""} ? }, ? methods:{ ? ? handle(msg){ ? ? ? ? ? //定義handle方法,將自動(dòng)接收到的msg值給了自己的newMsg ? ? ? this.newMsg = msg ? ? } ? }, ? components: {HelloWorld} }; </script>
2.利用ref屬性。 ref是vue提供的內(nèi)部屬性,它其實(shí)相當(dāng)于類似"id""class"的標(biāo)識(shí)。首先在子組件上定義ref值(例:ref="son");然后在父組件中用this.\$refs.son即可獲取到son這個(gè)ref的組件,進(jìn)行操作。
子組件代碼:
<script> export default { ? name: "HelloWorld", ? data() { ? ? return {msg:"Welcome to Vue"} ?//即將向父?jìng)鬟f的data值 ? } }; </script>
父組件代碼:
<template> ? <div class="home"> ? ? <HelloWorld ref="son" /> ?//在子組件上定義一個(gè)ref 名為"son" ? </div> </template>
<script> import HelloWorld from "@/components/HelloWorld.vue"; export default { ? name: "Home", ? mounted(){ ? ? console.log(this.$refs.son.msg) ?//獲取到ref名為"son"的子組件內(nèi)msg數(shù)據(jù),在控制臺(tái)顯示“Welcome to Vue” ? }, ? components:{HelloWorld} }; </script>
兄弟關(guān)系組件
兄弟組件間的傳值方式我稱為 “總線轉(zhuǎn)送” 。原理很簡(jiǎn)單,利用父組件作為總線去轉(zhuǎn)送數(shù)據(jù)。首先,用上述講到的ref屬性或$emit()將組件A的數(shù)據(jù)向上傳遞給父組件;再由父組件通過(guò)props屬性向下傳值到組件B。
組件A代碼:
<template> ? <div>click me</div> </template>
<script> export default { ? name: "HelloWorld", ? data() { ? ? return {helloMsg:"Welcome to Vue"} //即將傳送的數(shù)據(jù)helloMsg ? } }; </script>
組件B代碼:
<template> ? <div> ? ? {{hiMsg}} ?//直接調(diào)用hiMsg,顯示“Welcome to Vue” ? </div> </template>
<script> export default { ? name: "Hi", ? props:{hiMsg:String} //用來(lái)接收父組件傳值的props屬性hiMsg }; </script>
父組件代碼:
<template> ? <div class="home"> ? ? <HelloWorld ref="son" @click.native="change"></HelloWorld> //定義ref屬性接收組件A傳來(lái)的數(shù)據(jù);點(diǎn)擊組件A觸發(fā)change() ? ? <Hi :hiMsg="msg"></Hi> ?//綁定組件B的hiMsg=msg,將數(shù)據(jù)轉(zhuǎn)發(fā)給組件B ? </div> </template>
<script> import HelloWorld from "@/components/HelloWorld.vue"; import Hi from "@/components/Hi.vue"; export default { ? name: "Home", ? data(){ ? ? return{ msg: "" } ? }, ? methods:{ ? ? change(){ ? ? ? return this.msg = this.$refs.son.helloMsg //將組件A傳來(lái)的helloMsg賦予this.msg ? ? } ? }, ? components:{HelloWorld, Hi} }; </script>
頁(yè)級(jí)關(guān)系組件
在vuecli3.0以后,項(xiàng)目結(jié)構(gòu)對(duì)組件級(jí)別作了明確的區(qū)別:入口組件(App) - 頁(yè)級(jí)組件(View) - 零件組件(Component)。一般在開(kāi)發(fā)中我們也會(huì)盡量按照這種結(jié)構(gòu)去劃分模塊,但頁(yè)級(jí)組件沒(méi)有父組件,如果說(shuō)頁(yè)級(jí)組件之間需要傳值,那就不能用“總線轉(zhuǎn)送”的方法了。
vuex:這是官方提供的一個(gè)插件,可稱為“狀態(tài)管理倉(cāng)庫(kù)”,用來(lái)管理項(xiàng)目中需要跨頁(yè)共享反復(fù)調(diào)用的狀態(tài)(狀態(tài)你可以理解成就是數(shù)據(jù)、變量、方法)。
vuex的存放倉(cāng)庫(kù)為Store,內(nèi)部結(jié)構(gòu)可分五大塊:
state
:狀態(tài)庫(kù),寄放基礎(chǔ)狀態(tài)。mutations
:同步方法,可理解成相當(dāng)于組件內(nèi)的computed屬性,接收state進(jìn)行改裝。actions
:異步方法,只針對(duì)mutations,接收并改裝。getters
:過(guò)濾器,對(duì)state調(diào)用前進(jìn)行改裝、派生并返回?cái)?shù)據(jù)。modules
:模塊,在復(fù)雜項(xiàng)目中用modules處理Store,使分工更清晰。
vuex令開(kāi)發(fā)中數(shù)據(jù)共享操作更得心應(yīng)手,還需要大家到官方文檔認(rèn)真學(xué)習(xí)。以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue-pdf插件實(shí)現(xiàn)pdf文檔預(yù)覽方式(自動(dòng)分頁(yè)預(yù)覽)
這篇文章主要介紹了vue-pdf插件實(shí)現(xiàn)pdf文檔預(yù)覽方式(自動(dòng)分頁(yè)預(yù)覽),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03element-ui中實(shí)現(xiàn)tree子節(jié)點(diǎn)部分選中時(shí)父節(jié)點(diǎn)也選中
這篇文章主要介紹了element-ui中實(shí)現(xiàn)tree子節(jié)點(diǎn)部分選中時(shí)父節(jié)點(diǎn)也選中的方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08vue實(shí)現(xiàn)token過(guò)期自動(dòng)跳轉(zhuǎn)到登錄頁(yè)面
本文主要介紹了vue實(shí)現(xiàn)token過(guò)期自動(dòng)跳轉(zhuǎn)到登錄頁(yè)面,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10vue實(shí)現(xiàn)播放后端flask發(fā)送的mp3文件
這篇文章主要為大家詳細(xì)介紹了vue如何實(shí)現(xiàn)播放后端flask發(fā)送的mp3文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01elementui中使用el-tabs切換實(shí)時(shí)更新數(shù)據(jù)
這篇文章主要介紹了elementui中使用el-tabs切換實(shí)時(shí)更新數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08vue中格式化時(shí)間過(guò)濾器代碼實(shí)例
這篇文章主要介紹了vue格式化時(shí)間過(guò)濾器,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04el-table實(shí)現(xiàn)轉(zhuǎn)置表格的示例代碼(行列互換)
這篇文章主要介紹了el-table實(shí)現(xiàn)轉(zhuǎn)置表格的示例代碼(行列互換),本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-02-02