大家好~~
在開始介紹 qiankun
的應(yīng)用通信之前丽啡,我們需要先了解微前端架構(gòu)如何劃分子應(yīng)用辱匿。
在微前端架構(gòu)中刃永,我們應(yīng)該按業(yè)務(wù)劃分出對(duì)應(yīng)的子應(yīng)用货矮,而不是通過(guò)功能模塊劃分子應(yīng)用。這么做的原因有兩個(gè):
- 在微前端架構(gòu)中斯够,子應(yīng)用并不是一個(gè)模塊囚玫,而是一個(gè)獨(dú)立的應(yīng)用,我們將子應(yīng)用按業(yè)務(wù)劃分可以擁有更好的可維護(hù)性和解耦性读规。
- 子應(yīng)用應(yīng)該具備獨(dú)立運(yùn)行的能力抓督,應(yīng)用間頻繁的通信會(huì)增加應(yīng)用的復(fù)雜度和耦合度。
綜上所述束亏,我們應(yīng)該從業(yè)務(wù)的角度出發(fā)劃分各個(gè)子應(yīng)用铃在,盡可能減少應(yīng)用間的通信,從而簡(jiǎn)化整個(gè)應(yīng)用碍遍,使得我們的微前端架構(gòu)可以更加靈活可控定铜。
上面的這段話是引自這篇好文,這篇文章中主要介紹了兩種主應(yīng)用和微應(yīng)用的通信方式
第一種是 qiankun
官方提供的通信方式 - Actions
通信怕敬,適合業(yè)務(wù)劃分清晰揣炕,比較簡(jiǎn)單的微前端應(yīng)用,一般來(lái)說(shuō)使用第一種方案就可以滿足大部分的應(yīng)用場(chǎng)景需求东跪。
第二種是基于 redux
實(shí)現(xiàn)的通信方式 - Shared
通信畸陡,適合需要跟蹤通信狀態(tài),子應(yīng)用具備獨(dú)立運(yùn)行能力虽填,較為復(fù)雜的微前端應(yīng)用丁恭。
我寫這篇博客的主要原因是探究主應(yīng)用和多個(gè)微應(yīng)用之間如何使用Vuex來(lái)進(jìn)行狀態(tài)管理,這其實(shí)是對(duì)于上面通信方式中斋日,第二種方式的補(bǔ)充牲览。
場(chǎng)景
項(xiàng)目現(xiàn)狀:
- 主應(yīng)用是Vue技術(shù)棧,使用Vuex進(jìn)行狀態(tài)管理
- 多個(gè)微應(yīng)用也是Vue技術(shù)棧桑驱,并且都可能使用Vuex進(jìn)行狀態(tài)管理
想要解決的問(wèn)題:
- 主應(yīng)用與微應(yīng)用的通信
- 微應(yīng)用之間的通信
通信方式的選擇:
-
qiankun
官方提供的通信方式 -Actions
通信竭恬。優(yōu)點(diǎn):
- 使用簡(jiǎn)單;
- 官方支持性高熬的;
- 適合通信較少的業(yè)務(wù)場(chǎng)景;
缺點(diǎn):
- 子應(yīng)用獨(dú)立運(yùn)行時(shí)赊级,需要額外配置無(wú)
Actions
時(shí)的邏輯押框; - 子應(yīng)用需要先了解狀態(tài)池的細(xì)節(jié),再進(jìn)行通信理逊;
- 由于狀態(tài)池?zé)o法跟蹤橡伞,通信場(chǎng)景較多時(shí)盒揉,容易出現(xiàn)狀態(tài)混亂、維護(hù)困難等問(wèn)題兑徘;
-
使用Vuex進(jìn)行狀態(tài)管理
優(yōu)點(diǎn):
- 子應(yīng)用無(wú)法隨意污染主應(yīng)用的狀態(tài)池刚盈,只能通過(guò)主應(yīng)用暴露的
shared
實(shí)例的特定方法操作狀態(tài)池,從而避免狀態(tài)池污染產(chǎn)生的問(wèn)題挂脑。 - 子應(yīng)用將具備獨(dú)立運(yùn)行的能力
缺點(diǎn):
暫時(shí)沒(méi)有想到藕漱。。崭闲。肋联。
- 子應(yīng)用無(wú)法隨意污染主應(yīng)用的狀態(tài)池刚盈,只能通過(guò)主應(yīng)用暴露的
核心思想
主要就是在做微前端集成時(shí),將主應(yīng)用的store共享給所有微應(yīng)用刁俭,針對(duì)不同微應(yīng)用可以進(jìn)行模塊化設(shè)置橄仍,這樣使得共享的state更加易于管理。
具體實(shí)現(xiàn)(微應(yīng)用原本就沒(méi)有使用Vuex
進(jìn)行狀態(tài)管理)
step1:主應(yīng)用向微應(yīng)用傳遞store
實(shí)例牍戚。
registerMicroApps(
[
{
name: "chai-project",
entry: "http://localhost:8080",
container: '#yourContainer',
activeRule: "/chaiQiankunTest/ffff",
props: {
store //共享主應(yīng)用的store實(shí)例
}
}
],
{
beforeLoad: [
app => {
console.log("before load", app);
}
], // 掛載前回調(diào)
beforeMount: [
app => {
console.log("before mount", app);
}
], // 掛載后回調(diào)
afterUnmount: [
app => {
console.log("after unload", app);
}
] // 卸載后回調(diào)
}
)
step2:微應(yīng)用使用主應(yīng)用共享的store實(shí)例
針對(duì)第一種情況侮繁,就是在入口文件中引入vuex
,并使用該插件如孝,進(jìn)而在創(chuàng)建vue
實(shí)例的時(shí)候鼎天,傳入主應(yīng)用共享的store
實(shí)例。
import Vuex from 'vuex'
Vue.use(Vuex);
function render (props) {
const store = props.store;
// 在 render 中創(chuàng)建 VueRouter暑竟,可以保證在卸載微應(yīng)用時(shí)斋射,移除 location 事件監(jiān)聽,防止事件污染
router = new Router({
// 運(yùn)行在主應(yīng)用中時(shí)但荤,添加路由命名空間 /chaiQiankunTest/ffff
base: window.__POWERED_BY_QIANKUN__ ? 'chaiQiankunTest/ffff' : '/',
mode: 'history',
routes
});
// 掛載應(yīng)用
instance = new Vue({
router,
store,//主應(yīng)用共享的store實(shí)例
render: (h) => h(App)
}).$mount('#app');
}
step3:驗(yàn)證主應(yīng)用和微應(yīng)用之間是否可以完成通信罗岖,狀態(tài)同步。
驗(yàn)證的思路就是
(1)在主應(yīng)用和微應(yīng)用的頁(yè)面上添加改變同一個(gè)state
的方法腹躁,并且利用computed
實(shí)時(shí)顯示該state
的狀態(tài)值桑包。
(具體的實(shí)現(xiàn)代碼這里就不詳細(xì)給出)
驗(yàn)證用例主要是
(1)點(diǎn)擊主應(yīng)用按鈕,修改state
值之后纺非,主應(yīng)用和微應(yīng)用的頁(yè)面上都實(shí)時(shí)觸發(fā)computed
屬性哑了,展示最新狀態(tài)值
(2)點(diǎn)擊微應(yīng)用按鈕,修改state
值之后烧颖,主應(yīng)用和微應(yīng)用的頁(yè)面上都實(shí)時(shí)觸發(fā)computed
屬性弱左,展示最新狀態(tài)值
驗(yàn)證的結(jié)果
不論是點(diǎn)擊主應(yīng)用的按鈕,還是點(diǎn)擊微應(yīng)用的按鈕炕淮,主應(yīng)用的computed
屬性成功被觸發(fā)拆火,微應(yīng)用始終未能正常監(jiān)聽到狀態(tài)值得改變,computed
屬性從未被觸發(fā)。
這里查閱了蠻多的資料们镜,沒(méi)能看到有大神對(duì)qiankun使用Vuex
的經(jīng)驗(yàn)總結(jié)(這里也發(fā)現(xiàn)自己有點(diǎn)過(guò)于依賴網(wǎng)絡(luò)搬磚币叹,有些問(wèn)題積極思考是能夠找到答案的)
step4:bug修復(fù)
微應(yīng)用的computed
始終沒(méi)有被觸發(fā),底層原因就是其依賴屬性this.$store.state.count
是非相應(yīng)式的模狭,這會(huì)導(dǎo)致難以觸發(fā)颈抚。
computed: {
childCount: {
get (){
return this.$store.state.count;
}
}
}
Vuex
正常使用的時(shí)候,所有的狀態(tài)值都是響應(yīng)式的嚼鹉,可以直接用于Vue
頁(yè)面之中贩汉,但是這里是非響應(yīng)式的,導(dǎo)致這個(gè)的原因其實(shí)十分簡(jiǎn)單反砌。這里的store
實(shí)例是由主應(yīng)用傳遞過(guò)來(lái)的雾鬼,store
中的狀態(tài)對(duì)于主應(yīng)用的Vue
實(shí)例而言是親兒子,是響應(yīng)式的宴树,在微應(yīng)用中策菜,雖然可以使用共享store
實(shí)例中的commit
方法,但是對(duì)于微應(yīng)用的Vue
實(shí)例而言酒贬,不是親兒子又憨,是非響應(yīng)式的,這樣分析之后锭吨,解決方案就十分明確:
在微應(yīng)用中將共享的store實(shí)例進(jìn)行響應(yīng)式設(shè)置蠢莺,這是Vue現(xiàn)有的API方法Vue.observable(store)
如此處理之后,不論主應(yīng)用還是微應(yīng)用中零如,修改共享store
的state
狀態(tài)值躏将,在主應(yīng)用和微應(yīng)用中都能夠?qū)崟r(shí)感知,并對(duì)其做出響應(yīng)的反饋考蕾。
具體實(shí)現(xiàn)(微應(yīng)用本身就有自己store
實(shí)例)
這種情況主要考慮的是兩種方案
-
主應(yīng)用需要提前得知子應(yīng)用的
store
內(nèi)容祸憋,將其與主應(yīng)用的store進(jìn)行某種融合,這樣子應(yīng)用在集成環(huán)境中以及在獨(dú)立運(yùn)行時(shí)都能夠正常運(yùn)行肖卧。缺點(diǎn):這方方案會(huì)導(dǎo)致主應(yīng)用和子應(yīng)用相互耦合過(guò)強(qiáng)蚯窥,并且主應(yīng)用和子應(yīng)用都要維護(hù)一份子應(yīng)用的
store
,增加工作量塞帐,過(guò)于笨重拦赠。 -
主應(yīng)用依舊只傳遞主應(yīng)用的
store
,子應(yīng)用的store依舊在使用葵姥,也就是在子應(yīng)用中既可以操作主應(yīng)用的store
荷鼠,也可以操作子應(yīng)用的store
。優(yōu)點(diǎn):主應(yīng)用只需關(guān)注需要交互的狀態(tài)即可牌里,不用關(guān)心子應(yīng)用原本的
store
內(nèi)容颊咬。子應(yīng)用也只需關(guān)注自己的store
內(nèi)容即可务甥,降低耦合牡辽,減輕復(fù)雜度喳篇。
父子應(yīng)用store分離的方案實(shí)現(xiàn)
這里基于父應(yīng)用已經(jīng)共享自己的store
,并且主應(yīng)用和子應(yīng)用之間已經(jīng)能夠完成對(duì)于主應(yīng)用的state
狀態(tài)變化的響應(yīng)态辛◆锢剑考慮如何在子應(yīng)用中使用兩個(gè)store
,new Vue()
中目前注入的是主應(yīng)用的store
奏黑,那子應(yīng)用本身的store
如何全局注冊(cè)呢炊邦?仔細(xì)思考后,其實(shí)很簡(jiǎn)單熟史,只需要在入口文件中添加如下一行代碼:
Vue.prototype.microStore = microStore;
如此一來(lái)馁害,在子應(yīng)用的各個(gè)頁(yè)面都能夠通過(guò)this.microStore
訪問(wèn)自身的store
。
computed: {
microCount: {
get (){
return this.microStore.state.microCount;
}
}
}
總結(jié)
到此蹂匹,關(guān)于在qiankun的集成中碘菜,主應(yīng)用和子應(yīng)用使用Vuex進(jìn)行通信的基本使用方法介紹結(jié)束了,缺少了子應(yīng)用和子應(yīng)用之間的一個(gè)實(shí)驗(yàn)限寞,大家有興趣可以試試忍啸。