# 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|