# micro-shared **Repository Path**: suqingyao/micro-shared ## Basic Information - **Project Name**: micro-shared - **Description**: 一个用于微前端的通信模块 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-07-30 - **Last Updated**: 2021-08-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ⚡一个用于微前端的通信模块 micro-shared以`redux`为核心,采用`发布-订阅模式`进行封装,实现应用间通信数据上的`响应式`,并在代码结构上实现`模块化`,使用上编写方式及api类似vuex,上手难度低, 并可`适用多框架`(如vue、react) 代码: github or gitee 文档: ⚡qiankun微前端中的应用通信(四)-上手micro-shared及原理解析 ## 安装 ``` yarn add micro-shared ``` ## 在项目中使用 1. 首先在主应用里创建pool文件夹 `@/pool` ``` pool ├── index.ts └── modules ├── locale.ts └── user.ts ``` 2. 然后开始编写user.ts ```typescript import { Mutation } from 'micro-shared'; interface UserInfo { username: string, } interface State { userinfo?: UserInfo | Record } const state:State = { userinfo: {}, }; const reducer = (userState: State = state, mutation: Mutation): State => { switch (mutation.type) { case 'SET_USERINFO': return { ...userState, userinfo: mutation.payload, }; break; default: return userState; } }; const action = { getUserinfo: ( { state }: any ): UserInfo | Record => { return state.userinfo || {}; }, setUserinfo: ({ commit }: any, userinfo: UserInfo): void => { commit({ type: 'SET_USERINFO', payload: userinfo, }); }, }; export default { name: 'user', reducer, action }; ``` 可以看出整个user由三部分组成`state`、`reducer`、`action` 同时对外暴露`name`、`reducer`、`action` 其中name为模块名,action是微应用唯一能直接访问的api, 而state只能由reducer改变 ```mermaid graph TD action --> reducer --> state ``` 3. 将user模块导入,同时生成shared ```typescript // pool/index.ts import Shared from 'micro-shared'; import User from './modules/user'; import Locale from './modules/locale'; const shared = new Shared({ modules: { User, Locale, }, }) export default shared.getShared(); ``` 至此shared已编写完毕,接下来通过qiankun的props传给微应用即可。 4. 在主应用项目中,进行qiankun的微应用注册的地方 ```typescript import { registerMicroApps, start } from 'qiankun'; import shared from '@/pool'; registerMicroApps([ { name: 'micro', entry: '//localhost:8888', container: '#nav', activeRule: '/micro', props: { shared }, }, ]); start(); ``` 5. 在微应用中,接收shared实例 ```typescript // @/main.ts 已隐藏无关代码 import SharedModule from '@/pool'; function render(props: any = {}) { const { container, shared = SharedModule.getShared() } = props; SharedModule.overloadShared(shared); } ``` 6. 在微应用中创建 @/pool目录 (也是上一步里, `import SharedModule`的来源) ``` pool ├── index.ts ``` 而`@/pool/index.ts`也十分简单,相当于只需做模块注册即可 ```typescript import SharedModule from 'micro-shared/sharedmodule'; import { Shared } from './shared';// 本地模块 SharedModule.initShared(Shared);// 加载本地模块 export default SharedModule; ``` 第二行和第三行是用于加载本地shared实例(确保微应用独立运行时不会缺失shared),如果不考虑独立运行的话,这两行代码也可以删去。 7. 现在你就可以在微应用自身的store里使用了 ```typescript import Vue from 'vue'; import Vuex from 'vuex'; import SharedModule from '@/pool';// 从第6步创建的pool目录里引入 Vue.use(Vuex); let shared:any = null; export interface UserInfo { username: string, } interface State { locale: string, userinfo: UserInfo | Record, } export default new Vuex.Store({ state: { locale: '', userinfo: {}, }, mutations: { SET_LOCALE: (state: State, locale: string) => { state.locale = locale; }, SET_USERINFO: (state: State, userinfo: UserInfo) => { state.userinfo = userinfo; }, }, actions: { /* 初始化shared模块 建议在main.ts中,在执行完SharedModule.overloadShared(shared)后就执行该初始化 */ initShared() { shared = SharedModule.getShared(); this.dispatch('setLocale'); this.dispatch('setUserinfo'); SharedModule.subscribe([ (stateName: string) => { if(stateName === 'locale') this.dispatch('setLocale'); }, (stateName: string) => { if(stateName === 'user') this.dispatch('setUserinfo'); }, ]); }, setLocale({ commit }) { const locale = shared.dispatch('locale/getLocale'); commit('SET_LOCALE', locale); }, setUserinfo({ commit }) { const userinfo = shared.dispatch('user/getUserinfo'); commit('SET_USERINFO', userinfo); }, }, getters: { locale: (state: State) => state.locale, userinfo: (state: State) => state.userinfo, }, modules: { }, }); ``` 1. `SharedModule.subscribe` 用于注册订阅事件。通过传入回调函数进行订阅, 可以数组形式批量传入,当pool内数据有变化时(监听到redux提供的set方法执行了),会通过回调函数统一发布。 2. 注册的订阅事件可以接收一个参数 stateName,该参数会返回当前发生改变的state, 例如此次demo的state有 user 和 locale, 当user里的userinfo发生改变时, 每个订阅事件都会获得`stateName`参数,告诉你`user`这个state发生了改变,这可以更好的帮助你决定更新哪些模块的状态 3. 由于2实现的核心是`浅比较`,因此当`stateName`为空字符串时,可以判断出是嵌套较深的state发生了改变,这在一定程度上也可以知道到底是哪个state改变了 ## api ### SharedModule |api|说明| |--|--| |initShared|加载本地shared| |overloadShared|用于重载SharedModule内的shared实例| |getShared|获取SharedModule内部的shared实例| |subscribe|注册订阅事件(可传数组),在state发生改变后会触发此处订阅的事件| ### shared |api|说明| |--|--| |dispatch|类似vuex的store.dispatch,用于调用不同模块的action|