vue非父子組件通信問題及解決方法
問題描述:
最近在做登錄部分時遇到一個場景,當(dāng)點(diǎn)擊 “用戶”按鈕時,首先渲染login組件,在用戶登錄后直接跳轉(zhuǎn)到用戶信息界面(user組件)。這里遇到了需要將login組件通過異步請求獲得的用戶信息傳向 user組件,但是login和login組件不是父子組件,就暫稱為兄弟組件吧。 簡而言之,我要解決的就是兄弟組件之間的信息傳遞問題。
//位于login.vue 中
export default {
methods:{
login(){
this.$axios({
method: 'post',
url: '/student/login/',
data: {
username: this.username,
password: this.password
}
})
.then(function (response) {
this.$router.replace({path: 'user'});
}.bind(this))
.catch(function (error) {
console.log(error);
alert('用戶名或密碼錯誤');
});
}
}
}
在異步請求完成后,就跳轉(zhuǎn)到user組件中,但是response的請求返回信息就無法傳到非父子組件的user組件中。
.............................................................................................................................................................................................................
解決問題:
一、首先我想到了將login組件 和 user組件放到一起(兩個組件合2為1),加避免了組件間的信息傳遞,但是這種解決方案太low,破壞了項(xiàng)目原有的結(jié)構(gòu)。
二、查文檔得知了
非父子關(guān)系的兩個組件之間也需要通信。在簡單的場景下,可以使用一個空的 Vue 實(shí)例作為事件總線:
var bus = new Vue()
// 觸發(fā)組件 A 中的事件
bus.$emit('id-selected', 1)
// 在組件 B 創(chuàng)建的鉤子中監(jiān)聽事件
bus.$on('id-selected', function (id) {
// ...
})
以自己遇到的問題為例,寫出具體的實(shí)現(xiàn):(warning: 我自己遇到的情況不能用這種簡單的方式解決)
最好先新建一個js文件,來創(chuàng)建出我們的eventBus,我們把它命名為bus.js
import Vue from 'vue'; export default new Vue();
然后在 login.vue 文件中:
//位于login.vue 中
import Bus from '../bus.js';
export default {
methods:{
login(){
this.$axios({
method: 'post',
url: '/student/login/',
data: {
username: this.username,
password: this.password
}
})
.then(function (response) {
/*
* 這里的 'login-on'是在Bus中自己構(gòu)造的一個事件(不需要在別處申明),通過emit()函數(shù)
* 手動觸發(fā)這個事件,然后在user.vue 中可以監(jiān)聽這個事件,一旦發(fā)現(xiàn)事件觸發(fā),就可以利用
* 回調(diào)函數(shù)接收 response 這個對象,達(dá)到信息傳遞的目的
* */
Bus.$emit('login-on',response);
this.$router.replace({path: 'user'});
}.bind(this))
.catch(function (error) {
console.log(error);
alert('用戶名或密碼錯誤');
});
}
}
}
在user.vue文件中:
//位于user.vue 中
import Bus from '../bus.js';
export default {
mouted : {
Bus.$on('login-on', message => { // 這里的message就是從login.vue中傳來的數(shù)據(jù)
console.log(message);
});
}
}
這樣就完成了數(shù)據(jù)傳遞。
但是在測試時發(fā)現(xiàn)在user.vue組件的監(jiān)聽 沒有被觸發(fā)
分析:在我遇到的情境中,login.vue組件和user.vue 組件是互相替代的關(guān)系,即需要從login組件通過vue-router跳轉(zhuǎn)到user組件,在login.vue銷毀后才開始渲染user.vue組件,所以在user.vue中的
Bus.$on('login-on', message =>
監(jiān)聽是在事件以及觸發(fā)之后才開始,自然不會產(chǎn)生回調(diào)函數(shù)。
由此可以看出,官方推薦的eventbus 解決方案的缺陷在于, 在數(shù)據(jù)傳遞過程中,兩個組件必須都已經(jīng)被渲染過。我的這種情景下,這種方法不適用。
三、vuex解決方案:
熟悉vuex的大佬們請直接跳過吧。
最好在src的根目錄下新建一個文件,叫 store.js
//位于store.js 中
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
/*
* state指的就是儲存的數(shù)據(jù),
* 下面的數(shù)據(jù)是我在項(xiàng)目中需要用的數(shù)據(jù)字段
* */
state: {
has_login: false,
id: 1,
mobile_num: '',
name: ''
},
/*
* mutations里面規(guī)定的就是想要改變state(數(shù)據(jù))的動作函數(shù),
* 下面的user_message 就是我將傳入的message賦值給倉庫中的
* state數(shù)據(jù)字段,達(dá)到更新數(shù)據(jù)的目的
* */
mutations: {
user_message (state, message) {
state.has_login = true;
state.id = message.data.id;
state.mobile_num = message.data.mobile_num;
state.name = message.data.name;
}
}
})
然后在login.vue組件中,提交收到的用戶信息
//位于login.vue 中
import userMessage from '../store';
export default new Vuex.Store({
methods: {
loginSubmit () {
this.$axios({
method: 'post',
url: '/student/login/',
data: {
username: this.username,
password: this.password
}
})
.then(function (response) {
//這里調(diào)用 store.js中 mutations里面的user_message函數(shù),從而改變倉庫中的state數(shù)據(jù)
userMessage.commit('user_message', response);
this.$router.replace({path: 'user'});
}.bind(this))
.catch(function (error) {
console.log(error);
alert('用戶名或密碼錯誤');
});
}
})
最后在user.vue組件中接收vuex倉庫中存儲的信息,即先引入倉庫
//位于user.vue 中 import userMessage from '../store';
然后可以直接將 userMessage.state 賦值給user.vue作用域中的數(shù)據(jù)字段,同時,vuex 的state有熱更新的屬性,對于數(shù)據(jù)的同步很有幫助,優(yōu)點(diǎn)良多。
所以,中大型的項(xiàng)目還是在一開始就直接使用vuex是明智的決定,對于開發(fā)有很大的便利。
總結(jié)
以上所述是小編給大家介紹的vue非父子組件通信問題解決方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
vue-quill-editor+plupload富文本編輯器實(shí)例詳解
這篇文章主要介紹了vue-quill-editor+plupload富文本編輯器實(shí)例詳解,需要的朋友可以參考下2018-10-10
Vue中使用Printjs插件實(shí)現(xiàn)打印功能
Print.js 主要是為了幫助我們直接在我們的應(yīng)用程序中打印 PDF 文件,無需離開界面,也無需使用嵌入,這篇文章主要介紹了Vue中使用Printjs插件實(shí)現(xiàn)打印功能,需要的朋友可以參考下2022-08-08
vue、uniapp實(shí)現(xiàn)組件動態(tài)切換效果
在Vue中,通過使用動態(tài)組件,我們可以實(shí)現(xiàn)組件的動態(tài)切換,從而達(dá)到頁面的動態(tài)展示效果,這篇文章主要介紹了vue、uniapp實(shí)現(xiàn)組件動態(tài)切換,需要的朋友可以參考下2023-10-10
15 分鐘掌握vue-next函數(shù)式api(小結(jié))
這篇文章主要介紹了15 分鐘掌握vue-next函數(shù)式api(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
解決vue-router中的query動態(tài)傳參問題
下面小編就為大家分享一篇解決vue-router中的query動態(tài)傳參問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03

