主要探究下主應用和多個微應用之間如何使用Vuex來進行狀態管理,這其實是對上一篇文章中通信方式第二種方式的補充,因為 vue 主要還是使用 vuex 作為狀態管理。
一、場景選擇
1、項目現狀:
- 主應用是Vue技術棧,使用Vuex進行狀態管理
- 多個微應用也是Vue技術棧,並且都可能使用Vuex進行狀態管理
2、想要解決的問題:
- 主應用與微應用的通信
- 微應用之間的通信
3、通信方式的選擇:
qiankun
官方提供的通信方式 -Actions
通信 (不多說,看上篇文章即可);- 使用shared實例通信,使用Vuex進行狀態管理
- 子應用無法隨意污染主應用的狀態池,只能通過主應用暴露的
shared
實例的特定方法操作狀態池,從而避免狀態池污染產生的問題。 - 子應用將具備獨立運行的能力
二、核心思想
三、具體實現
(一)微應用原本就沒有使用Vuex
進行狀態管理
1、主應用向微應用傳遞store
實例
registerMicroApps([ { name: "chai-project", entry: "//localhost:8080", container: '#yourContainer', activeRule: "/micro", props: { store //共享主應用的store實例 } } ])
2、微應用使用主應用共享的store實例
針對第一種情況,就是在入口文件中引入vuex
,並使用該插件,進而在創建vue
實例的時候,傳入主應用共享的store
實例。
import Vuex from 'vuex' Vue.use(Vuex); function render (props) { const store = props.store; // 在 render 中創建 VueRouter,可以保證在卸載微應用時,移除 location 事件監聽,防止事件污染 router = new Router({ // 運行在主應用中時,添加路由命名空間 /micro base: window.__POWERED_BY_QIANKUN__ ? '/micro' : '/', mode: 'history', routes }); // 掛載應用 instance = new Vue({ router, store,//主應用共享的store實例 render: (h) => h(App) }).$mount('#app'); }
3、驗證主應用和微應用之間是否可以完成通信,狀態同步。
驗證的思路就是:在主應用和微應用的頁面上添加改變同一個state
的方法,並且利用computed
實時顯示該state
的狀態值。
驗證用例主要是:
- 點擊主應用按鈕,修改
state
值之后,主應用和微應用的頁面上都實時觸發computed
屬性,展示最新狀態值 - 點擊微應用按鈕,修改
state
值之后,主應用和微應用的頁面上都實時觸發computed
屬性,展示最新狀態值
驗證的結果:不論是點擊主應用的按鈕,還是點擊微應用的按鈕,主應用的computed
屬性成功被觸發,微應用始終未能正常監聽到狀態值得改變,computed
屬性從未被觸發。
4、bug修復:
微應用的computed
始終沒有被觸發,底層原因就是其依賴屬性this.$store.state.count
是非響應式的,這會導致難以觸發。
Vuex
正常使用的時候,所有的狀態值都是響應式的(需要主動在 state 里聲明的才是響應式的),可以直接用於Vue
頁面之中,但是這里是非響應式的,導致這個的原因其實十分簡單。
這里的store
實例是由主應用傳遞過來的,store
中的狀態對於主應用的Vue
實例而言是親兒子,是響應式的,在微應用中,雖然可以使用共享store
實例中的commit
方法,但是對於微應用的Vue
實例而言,不是親兒子,是非響應式的,這樣分析之后,解決方案就十分明確:在微應用中將共享的store實例進行響應式設置,這是Vue現有的API方法Vue.observable(store)。
如此處理之后,不論主應用還是微應用中,修改共享store
的state
狀態值,在主應用和微應用中都能夠實時感知,並對其做出響應的反饋。
(二)微應用本身就有自己store
實例
這種情況主要考慮的是兩種方案:
-
主應用需要提前得知子應用的
store
內容,將其與主應用的store進行某種融合,這樣子應用在集成環境中以及在獨立運行時都能夠正常運行。缺點:這方方案會導致主應用和子應用相互耦合過強,並且主應用和子應用都要維護一份子應用的
store
,增加工作量,過於笨重。 -
主應用依舊只傳遞主應用的
store
,子應用的store依舊在使用,也就是在子應用中既可以操作主應用的store
,也可以操作子應用的store
。優點:主應用只需關注需要交互的狀態即可,不用關心子應用原本的
store
內容。子應用也只需關注自己的store
內容即可,降低耦合,減輕復雜度。
這里基於父應用已經共享自己的store
,並且主應用和子應用之間已經能夠完成對於主應用的state
狀態變化的響應。
考慮如何在子應用中使用兩個store
,new Vue()
中目前注入的是主應用的store
,那子應用本身的store
如何全局注冊呢?仔細思考后,其實很簡單,只需要在入口文件中添加如下一行代碼:
Vue.prototype.microStore = microStore;
如此一來,在子應用的各個頁面都能夠通過this.microStore
訪問自身的store
。
computed: { microCount: { get (){ return this.microStore.state.microCount; } } }
主要來自於對下面這篇文章的學習,也是在查詢微前端應用間通信方案時看到的,是對上一篇文章的補充。起初使用微前端時看的不是很能清晰理解,昨天自己在項目中實戰主子應用間通信成功之后再回過頭來看這篇文章,確實就清晰多了:《基於qiankun的微前端最佳實踐-通信篇(Vuex)- https://www.jianshu.com/p/b2a77373c09e》