概述:
使用单独Vue实例保存子应用实例 子应用查询表单数据 子应该表格数据
父级应用:
1. 父级应用中创建VueEmit.js文件中 new Vue() 用于存放子应用实例
basic应用
vueEmit.js
import Vue from 'vue'
var VueEvent = new Vue()
VueEvent.loadedApplicationMap = {} // 子应用缓存
VueEvent.isAddTab = false // 记录tab页签的变化前的值
export default VueEvent
2.父级应用中提供卸载子应用并缓存子应用的方法unmountCache
utils.js
// 父应用提供unmountCache方法
export function unmountCache(cacheKey, instance) {
// 此处永远只会保存首次加载生成的实例
let cachedInstance = {}
cachedInstance = instance
// keepalive设置为必须 防止进入时再次created,同keep-alive实现
if (!cachedInstance._vnode.data.keepAlive) cachedInstance._vnode.data.keepAlive = true
// loadedApplicationMap用于是key-value形式,用于保存当前应用的实例
vueEvent.loadedApplicationMap[cacheKey] = cachedInstance
}
子级应用:
1.main.js中mount(props)挂载方法中获取父级应用缓存的实例数据(router/isAddTab/getMicroAppCache)
import Vue from 'vue'
import App from './App.vue'
// import router from './router'
import routes from './router'
import RcAgGrid from '@redcarp/aggrid'
Vue.use(RcAgGrid)
import '@/assets/lib/webfonts/iconfont.css'
import '@it-web/element-ui/lib/theme-chalk/index.css'
import '@/assets/lib/index.css'
import '@/assets/styles/main.css'
import store from './store/store'
import './utils'
import './api/http'
import i18n from './assets/language/index'
import '@/utils/viewport'
import './utils/buryingPoint' // 火山引擎埋点
// import ElementUI from '@it-web/element-ui'
// import locale from '@it-web/element-ui/lib/locale/lang/zh-CN'
import VueRouter from 'vue-router'
import '@/directive/dialog'
import {
getCurrentTime
} from '@redcarp/utils'
import {
isNotExistInTab
} from '@/utils/common'
import actions from './actions'
import * as moment from 'moment'
import './components'
import RcCommon from '@redcarp/common'
import '@redcarp/common/redcarp-common.css'
import regularRules from '@/utils/regularRules' // 正则规则配置文件
import Cookies from 'js-cookie'
import { getUserInfo } from '@/api/user'
Vue.use(RcCommon)
Vue.prototype.$moment = moment
Vue.prototype.$getCurrentTime = getCurrentTime
// input-number精度,物料数量精度为0
Vue.prototype.$inputNumberPrecision = 0
Vue.prototype.$isNotExistInTab = isNotExistInTab
Vue.config.productionTip = false
Vue.prototype.$regularRules = regularRules // 正则规则配置
// 修复replace跳转同一个页面报错
const VueRouterReplace = VueRouter.prototype.replace
VueRouter.prototype.replace = function replace(to) {
return VueRouterReplace.call(this, to).catch(err => err)
}
let router = null
let instance = null
let mainService = null
async function render(mainData) {
const cachedInstance = mainData?.getMicroAppCache('declareManage') // 缓存的VNode
let cachedNode = null
router = new VueRouter({
base: window.__POWERED_BY_QIANKUN__ ? '/declareManage/' : process.env.BASE_URL,
mode: 'history',
routes
})
router = initRouter(router) // 路由判断
if (cachedInstance) {
cachedNode = cachedInstance._vnode // 缓存的VNode
router.apps.push(...cachedInstance.$router.apps)
}
if (cachedInstance) { // 存在缓存则判断是否需要跳转路由
router.onReady(() => {
const { path, query } = router.currentRoute
const { path: oldPath } = cachedInstance.$router.currentRoute
/*
* 以下代码解释:子应用实例不注销,导致当path === oldPath时页面不触发activated生命周期
* 使用中转页面
*/
// 当前路由和上一次卸载时不一致,则切换至新路由
if (path !== oldPath) {
cachedInstance.$router.push({ path, query })
} else {
cachedInstance.$router.push({ path: '/index', query })
Vue.nextTick(() => {
cachedInstance.$router.push({ path, query })
})
}
})
}
instance = await new Vue({
router,
store,
i18n,
render: cachedNode ? () => cachedNode : h => h(App) // 优先使用缓存vnode
}).$mount(mainData && mainData.container ? mainData.container.querySelector('#repairCore') : '#repairCore')
// 调用主应用store的方法
if (mainData) {
await mainData.data.store.dispatch('user/childAppLoadFinish')
}
}
if (!window.__POWERED_BY_QIANKUN__) {
render()
}
function initRouter(router) { // 路由拦截
router.beforeEach((to, from, next) => {
// 门户跳转token
if (to.query.accesstoken) {
Cookies.set('dahua_token', to.query.accesstoken)
localStorage.setItem('token', to.query.accesstoken)
}
if (!window.__POWERED_BY_QIANKUN__) {
if (to.query.token) {
const dataToken = to.query.token
Cookies.set('dahua_token', dataToken)
}
if (Cookies.get('dahua_token')) {
// 获取用户信息
if (localStorage.getItem('userInfo')) {
store.dispatch('user/setMicroUserInfo', JSON.parse(localStorage.getItem('userInfo') || '{}') || {})
localStorage.setItem('languageCode', localStorage.getItem('languageCode') || 'zh_CN')
next()
} else {
getUserInfo().then(res => {
if (Number(res.resultCode) === 200) {
store.dispatch('user/setMicroUserInfo', res.data)
localStorage.setItem('languageCode', res.data.languageCode)
next()
}
})
}
} else {
if (Cookies.get('dahua_token')) {
// 获取用户信息
getUserInfo().then(res => {
if (Number(res.resultCode) === 200) {
store.dispatch('user/setMicroUserInfo', res.data)
localStorage.setItem('languageCode', res.data.languageCode)
next()
}
})
} else {
next()
}
}
} else {
next()
}
})
return router
}
export async function bootstrap() {
console.log('vue app bootstraped')
}
export async function mount(props) {
actions.setActions(props)
store.dispatch('user/setMicroUserInfo', props.data.store.state.user.userInfo)
Vue.prototype.$microProps = props
Vue.prototype.$parentRouter = props.data.router
Vue.prototype.$isAddTab = props.isAddTab
Vue.prototype.$setAddTab = props.setAddTab
mainService = props
render(props)
}
// 应用每次 初出/卸载 会调用的方法,通常卸载微应用的应用实例
export async function unmount() {
mainService.unmountCache('declareManage', instance) // 主应用进行缓存子应用的VNode
}
2.render 方法中可以通过调用父级应用中获取缓存子应用的方法getMicroAppCache拿到子应用虚拟节点 判断是否有缓存 在new Vue 初始化子应用实例
时优先使用缓存节点
3.main.js中 unmount 卸载的时候调用父级应用中unmountCache方法卸载缓存子应用