1.父级组件
utils文件下
import store from "../store";
import {toLogin} from "./login";
/**
* @name 导入注册并启动微应用函数
*/
/**
* @name 声明一个常量准备将props内的部分内容储存起来
*/
const STORE = {};
/**
* @name 启动qiankun应用间通信机制
* @param {Function} initGlobalState 官方通信函数
* @description 注意:主应用是从qiankun中导出的initGlobalState方法,
* @description 注意:子应用是附加在props上的onGlobalStateChange, setGlobalState方法(只用主应用注册了通信才会有)
*/
const appStore = (initGlobalState) => {
/**
* @name 初始化数据内容
*/
const {onGlobalStateChange, setGlobalState} = initGlobalState({
ignore: '',
msg: '',
logout: false,
currentName: '',
isAdmin: false,
isshowLeftNav: false
});
/**
* @name 监听数据变动
* @param {Function} 监听到数据发生改变后的回调函数
* @des 将监听到的数据存入vuex
*/
onGlobalStateChange((value, prev) => {
console.log('[onGlobalStateChange - main]:', value, prev);
//测试数据同步
'msg' in value
&& store.dispatch('appstore/setMsg', value.msg)
// 角色名称
value.currentName && store.dispatch('user/updateStates', {
currentName: value.currentName
})
// 调回到管理后台
!value.isAdmin && store.dispatch('menu/updateStates', {isAdmin: false})
!value.isshowLeftNav && store.dispatch('menu/updateStates', {isshowLeftNav: false})
// 某个程序登录token 过期
value.logout && toLogin()
// value.token && store.dispatch('app/setToken', value.token);
// value.appsRefresh && window?.location?.reload?.();
});
/**
* @name 改变数据并向所有应用广播
*/
setGlobalState({
ignore: 'main',
// msg: '来自master动态设定的消息'
});
/**
* @name 将你需要的数据存起来,供下面setState方法使用
*/
STORE.setGlobalState = setGlobalState;
STORE.name = 'main';
}
function isObject(val) {
return Object.prototype.toString.call(val) === "[object Object]";
}
/**
* @name 全局setState方法,修改的内容将通知所有微应用
* @param {Object} data 按照你设定的内容格式数据
*/
const setState = (data) => {
if (!isObject(data)) {
throw Error('data必须是对象格式');
}
STORE.setGlobalState?.({
ignore: 'main',
...data
})
}
export {
setState
}
export default appStore;
2.main文件引入
import Vue from 'vue'
import store from './store'
import App from './App.vue'
import router from './router'
import sso from '@oppo/helper-sso'
import VueLoading from 'vue-loading-template'
// qiankun
import {registerMicroApps, start, initGlobalState} from 'qiankun';
window.__POWERED_BY_QIANKUN_PARENT__ = true
// initGlobalState 配置
import appStore from "./utils/app-store";
Vue.prototype.bus = new Vue();
Vue.use(VueLoading, /** options **/)
// 统一样式引入
router.afterEach((to, from, next) => { // 默认滚动到顶部
window.scrollTo(0, 0);
});
// const getComputedStyle = window.getComputedStyle;
// window.getComputedStyle = (el, ...args) => {
// // 如果为shadow dom则直接返回
// if (el instanceof DocumentFragment) {
// return {};
// }
// return Reflect.apply(getComputedStyle, window, [el, ...args]);
// };
// 根据坐标(x, y)当获取一个子应用的元素的时候,会返回shadow root,并不会返回真正的元素
// const elementFromPoint = document.elementFromPoint;
// document.elementFromPoint = function (x, y) {
// const result = Reflect.apply(elementFromPoint, this, [x, y]);
// // 如果坐标元素为shadow则用该shadow再次获取
// if (result && result.shadowRoot) {
// return result.shadowRoot.elementFromPoint(x, y);
// }
// return result;
// };
// fix: 点击事件target为shadow元素的问题
// const {addEventListener: oldAddEventListener, removeEventListener: oldRemoveEventListener} = document;
// const fixEvents = ['click', 'mousedown', 'mouseup'];
// const overrideEventFnMap = {};
// const setOverrideEvent = (eventName, fn, overrideFn) => {
// if (fn === overrideFn) {
// return;
// }
// if (!overrideEventFnMap[eventName]) {
// overrideEventFnMap[eventName] = new Map();
// }
// overrideEventFnMap[eventName].set(fn, overrideFn);
// };
// const resetOverrideEvent = (eventName, fn) => {
// const eventFn = overrideEventFnMap[eventName]?.get(fn);
// if (eventFn) {
// overrideEventFnMap[eventName].delete(fn);
// }
// return eventFn || fn;
// };
// document.addEventListener = (event, fn, options) => {
// const callback = (e) => {
// // 当前事件对象为qiankun盒子,并且当前对象有shadowRoot元素,则fix事件对象为真实元素
// if (e.target.id?.startsWith('__qiankun_microapp_wrapper') && e.target?.shadowRoot) {
// fn({...e, target: e.path[0]});
// return;
// }
// fn(e);
// };
// const eventFn = fixEvents.includes(event) ? callback : fn;
// setOverrideEvent(event, fn, eventFn);
// Reflect.apply(oldAddEventListener, document, [event, eventFn, options]);
// };
// document.removeEventListener = (event, fn, options) => {
// const eventFn = resetOverrideEvent(event, fn);
// Reflect.apply(oldRemoveEventListener, document, [event, eventFn, options]);
// };
registerMicroApps([
//管理后台
{
name: 'admin',
entry: `${process.env.VUE_APP_QIANKUN_URL}`, // VUE_APP_QIANKUN_URL="//abc-admin-test.myoas.com"
container: '#container',
activeRule: '/admin',
props: {
data: store,
}
}
], {
beforeLoad: app => {
console.log('[主应用]before load app.name====>>>>>', app.name)
store.commit('appstore/setPageLoading', true)
},
beforeMount: [
app => {
store.dispatch('menu/updateStates', {appName: app.name})
console.log('[主应用][LifeCycle] before mount %c%s', 'color: green;', app.name);
},
],
afterMount: [
app => {
store.commit('appstore/setPageLoading', false)
app.name === 'admin' ? localStorage.setItem('admin', true): ''
app.name === 'admin' ? store.dispatch('menu/updateStates', {isAdmin: true}): ''
localStorage.getItem('admin') === 'true' ? store.dispatch('menu/updateStates', {isAdmin: true}) : ''
console.log('[主应用][LifeCycle] after mount %c%s', 'color: green;', app.name);
}
],
afterUnmount: [
app => {
console.log('[主应用][LifeCycle] after unmount %c%s', 'color: green;', app.name);
},
],
});
// qiankun配置
start({
prefetch: true, //预加载
sandbox: {
// strictStyleIsolation: true, // 样式沙箱开启
experimentalStyleIsolation: true,
}
})
// 开启 initGlobalState
appStore(initGlobalState)
new Vue({
router,
store,
sso,
render: h => h(App)
}).$mount('#app')