背景1:公司产品有多个,有sso login功能,即一个登录页面可以跳转多个产品。另外这个统一的登录页面也包含了头部header,可以跳转到公司人意其他内部产品,也有登出功能。
需求:需要在新开发的一个产品接入这个header,实现统一header。
总体技术实现:远程加载路径为「APP_XX_HEADER_URL」的header js文件,在vue template中能够使用<XX-Header />
调用。
不足:解决问题的时间久远,忘记当时遇到什么问题和一些思考过程了,这里只是记录最终的解决方案。
<template>
<component :is="type" :id-token="dxToken" @logout="apLogout"></component>
</template>
<script>
/* eslint-disable consistent-return */
import Vue from 'vue';
import { mapState } from 'vuex';
import SettingsService from '@/services/settings.js';
import Store from '@/store/index.js';
export default Vue.extend({
name: 'DaoHeader',
data() {
return {
type: 'div',
};
},
methods: {
getTokenInfo() {
SettingsService.getDxToken().then(res => {
const { id_token } = res?.data || {};
this.$store.commit('auth/saveDxToken', id_token);
});
},
setHeaderComponent(href) {
if (!href) return;
const Navigation = {};
const url = Store.state.auth.dxUrl;
const APP_DX_ARCH_HEADER_URL = `${url}/header/DxHeader.umd.min.js`;
if (!APP_DX_ARCH_HEADER_URL) {
return Navigation;
}
return import(/* webpackIgnore: true */ APP_DX_ARCH_HEADER_URL)
.then(() => {
const { DxHeader = Navigation } = window.DxHeader || {};
Vue.component('dxHeader', DxHeader);
this.type = 'dxHeader';
return DxHeader;
})
.catch(() => {
return Navigation;
});
},
apLogout() {
SettingsService.logout().then(() => {
this.$message.success('登出成功');
this.getTokenInfo();
});
},
},
computed: {
...mapState('auth', ['dxToken', 'dxUrl']),
isAuth() {
const { dxToken, dxUrl } = this;
return { dxToken, dxUrl };
},
},
watch: {
isAuth: {
deep: true,
immediate: true,
handler(val) {
const { dxUrl, dxToken } = val;
if (!dxUrl || !dxToken) return;
this.setHeaderComponent(dxUrl);
},
},
},
});
</script>
背景2,远程组件使用的是vue2,但本地使用的是vue3,怎么办?
<template>
<div id="dx" :class="type"></div>
</template>
<script setup>
import { Vue2InVue3 } from '@efox/emp-vuett';
import { render, ref, createVNode, getCurrentInstance } from 'vue';
import { useStore } from 'vuex';
import SettingsService from '@/service/settings.js';
const store = useStore();
const idToken = ref(store.state.settings.dxToken);
import(`${store.state.settings.dxUrl}/header/DxHeader.umd.min.js`);
const $message =
getCurrentInstance().appContext.config.globalProperties.$message;
const logout = () => {
SettingsService.logout()
.then(() => {
$message.success('登出成功');
location.reload();
})
.catch((e) => {
console.log(e);
});
};
setTimeout(() => {
const AsyncComp = window.DxHeader || { DxHeader: {} };
const container = document.createElement('div');
const idToken = store.state.settings.dxToken;
const header = createVNode(Vue2InVue3(AsyncComp.DxHeader, 'dx'), {
'id-token': idToken,
logout,
});
render(header, container);
}, 1000);
</script>
主要是借助国内某个大兄弟开源的库Vue2InVue3,挺好使 ^ ^