实现背景
项目中是使用的jeecg-boot低代码构建的前端开发环境,由于后期各个模块代码越来越多,打包慢,分支管理麻烦,领导要求使用微前端,每个模块拆分为子应用。
拆分子应用
由于jeecg里面自带qiankun,所以改造微前端我们使用qiankun来做
为了方便我们使用的qiankun自动挂载(registerMicroApps)的方式实现的
新的问题?
registerMicroApps方式使用了一段时间后,需求上需要切换tab页面时缓存子应用页面,页签关闭取消缓存,从菜单点击页面刷新。
从网上找了一些registerMicroApps实现缓存的方法,不是很适用,比如说:
https://zhuanlan.zhihu.com/p/548520855,3.1描述的方式实现,以及
https://blog.csdn.net/lunahaijiao/article/details/134657734,方案二实现方式。这两种都是registerMicroApps自动挂载的方式实现缓存页面。但是出现的问题是:一个子应用多个缓存页面就会出问题了
通过loadMicroApp实现
主应用
-
首先,主应用修改apps.js
const _apps = [
{
name: 'app1,
entry:
process.env.NODE_ENV === 'development'
? 'http://localhost:9529/'
: document.querySelector('html').dataset.app1Url,
container: '#contentApp1',
activeRule: 'app1', //路由匹配
sandbox: {
strictStyleIsolation: true // 开启样式隔离
}
},
{
name: 'app2',
entry:
process.env.NODE_ENV === 'development'
? 'http://localhost:3099/'
: document.querySelector('html').dataset.app2Url,
container: '#contentApp2',
activeRule: 'app2', //路由匹配
sandbox: {
strictStyleIsolation: true // 开启样式隔离
}
},
] -
修改index.js
/**
- qiankun配置
*/
import {
loadMicroApp,
} from 'qiankun'
import { apps } from './apps'
import { getProps, initGlState } from './state'
import { prefetchApps } from 'qiankun';
prefetchApps(apps);
/**
- 微应用注册
*/
function registerApps(item) {
const loader = loadMicroApp({
...item,
props: {
...getProps(),
}
}, {
sandbox: {
experimentalStyleIsolation: true, // 开启沙箱模式,实验性方案
}
})
// 定义全局状态
initGlState()
return loader
}
export default registerApps
- qiankun配置
-
state.js更改
/**
*公共数据
*/
import { initGlobalState } from 'qiankun'
import store from '../store'
import Vue from 'vue'
import { ACCESS_TOKEN, USER_NAME } from '@/store/mutation-types'
// 公共组件//定义传入子应用的数据
export function getProps() {
return {
data: {
publicPath: process.env.BASE_URL,
token: Vue.ls.get(ACCESS_TOKEN)
}
}
}/**
- 定义全局状态,并返回通信方法,在主应用使用,微应用通过 props 获取通信方法。
- @param state 主应用穿的公共数据
*/
export function initGlState() {
const info = {
userName: Vue.ls.get(USER_NAME),
isLogin: true,
closeCurrent: false,
produceTabsChange: 1,
approvalParams: '',
}
// 初始化state
const actions = initGlobalState(info)
// 设置新的值
actions.setGlobalState(info)
// 注册 观察者 函数 - 响应 globalState 变化,在 globalState 发生改变时触发该 观察者 函数。
actions.onGlobalStateChange((newState, prev) => {
if (!newState.isLogin) {
store.dispatch('Logout').then(() => {
window.location.reload()
})
}
if (newState.closeCurrent) {
store.dispatch('setCloseTab', true)
actions.setGlobalState({ closeCurrent: false })
}
})
// 将action对象绑到Vue原型上,为了项目中其他地方使用方便
Vue.prototype.$actions = actions
}
-
mian.js 修改
let activeApps = {}
router.beforeEach((to, from, next) => {
const conf = apps.find(item => to.path.includes(item.activeRule))
if (conf) {
store.dispatch('setOpenQianKun', true)
const cacheMicro = activeApps[conf.activeRule]
// 已缓存应用
if (cacheMicro) {
next()
return
}
// 未缓存应用
activeApps[conf.activeRule] = registerApps({ ...conf })
next()
} else {
unmountMicroApps()
store.dispatch('setOpenQianKun', false)
next()
}
})
export function unmountMicroApps () {
for (const key in activeApps) {
// 缓存的页面
const includedRoutes = Vue.ls.get(CACHE_INCLUDED_ROUTES) || []
// 子应用所有的页面
const subNameArr = Vue.ls.get(CACHE_SUB_ROUTES)[key]
let isInclude = false
includedRoutes.forEach(item => {
if (subNameArr.includes(item)) {
isInclude = true
}
})
// 子应用没有缓存的页面,卸载子应用
if (!isInclude) {
activeApps[key].unmount()
delete activeApps[key]
}
}
} -
子应用入口
-
在tab页面关闭时调用unmountMicroApps 方法
子应用
- user.js加上这段代码,解决主子应用路由冲突