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