流言四起
某位帅哥被领导叫进办公室并进行某种交易的事情曝光了,一时间办公室流传着各种版本,什么帅哥要给领导生孩子啊,什么领导一怒为红颜之类的声音一直存在😀。
作为当事人,为了避免这种离谱的流言继续流传,我只能出来解释了。
"咳咳,大家听好了,不是领导要给我生孩子,也不是领导因为我帅喜欢我,是领导叫我帮系统搞技术升级,用的是qiankun
框架,之前聊到主应用
模板,准备聊的是子应用
模板
说完,众人一副《你说的话我一句都不信》的表情。
我只好继续解释
"不是,你们什么眼神,真的是技术升级,不是什么奇怪的交易"。面对众人的眼神,我继续狡辩。
为了防止事情进一步恶化,我只能掏出证据了,来看代码吧(里面用到的UI库就不去除了)
先修改一下vue.config.js
文件,让子应用的构建可以适配qiankun
js
const { defineConfig } = require('@vue/cli-service')
const packageName = require('./package.json').name
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: {
output: {
library: `${packageName}-[name]`,
libraryTarget: 'umd',
chunkLoadingGlobal: `webpackJsonp_${packageName}`
},
},
devServer: {
// qiankun
headers: {
'Access-Control-Allow-Origin': '*'
}
}
})
主要修改构建的输出文件,根据qiankun
官网进行修改.
再看main.js
js
import './public-path'
import { createApp, App as typeApp } from 'vue'
import App from '@/App.vue'
import { createRouter, createWebHistory } from 'vue-router'
import { MicroAppStateActions } from 'qiankun'
import routes from '@/router'
import store from '@/store'
import permission from './permission'
import action from '@/directives/action'
import { VueAxios } from '@/api/request'
import ArcoVue from '@arco-design/web-vue'
import '@arco-design/web-vue/dist/arco.css'
interface LifecycleProps extends MicroAppStateActions {
container: Element
}
let router = null
let mountApp = null
let ROUTER_BASE = ''
export let app: typeApp
function render (props?: LifecycleProps): void {
mountApp = '#app'
if (props) {
mountApp = props.container.querySelector('#app') || ''
}
app = createApp(App)
router = createRouter({
history: createWebHistory(ROUTER_BASE),
routes
})
// 注册权限 store 路由
app.use(store)
.use(permission, {
router
})
.use(router).use(VueAxios).use(ArcoVue).use(action).mount(mountApp)
}
if (!window.__POWERED_BY_QIANKUN__) {
render()
}
// 注册qiankun全局状态
function qiankunStore (props: LifecycleProps) {
props.onGlobalStateChange && props.onGlobalStateChange(value => {
ROUTER_BASE = value.MAIN_ROUTER_BASE || ''
if (value.token) {
// 如果主应用有token 则设置token
store.commit('SET_TOKEN', {
value: value.token,
noSave: false
})
}
}, true)
// 注册修改全局状态的方法
store.commit('QIANKUN_SET_GLOBAL', props.setGlobalState)
}
export async function bootstrap () {
console.log('[vue] vue app bootstraped')
}
export async function mount (props: LifecycleProps) {
console.log('[subapp] props from main framework', props)
qiankunStore(props)
await render(props)
}
export async function unmount () {
app.unmount()
}
上面的代码是整个子应用中使用qiankun
的主要代码,主要使用qiankun
提供的几个API做一些事件的注册。
接下来是几个模板,直接上代码了。
App.vue
js
<template>
<a-config-provider :locale="local">
<router-view></router-view>
</a-config-provider>
</template>
<script lang="ts">
import zhCn from '@arco-design/web-vue/es/locale/lang/zh-cn'
export default {
name: 'App',
data () {
return {
local: zhCn
}
}
}
</script>
<style lang="less">
// 微前端容器高度
#SubappViewportWrapper {
height: 100%;
#SubappViewport {
height: 100%;
> div {
height: 100%;
}
}
}
.hide-micro-container {
#SubappViewportWrapper {
display: none;
}
}
</style>
这里设置了微前端容器的高度
BasicLayout.vue
js
<template>
<a-layout class="container">
<a-layout-sider collapsible breakpoint="xl">
<div class="logo">
<img alt="Vue logo" src="../assets/logo.png">
</div>
<a-menu
v-model:selected-keys="selectKeys"
v-model:openKeys="openKeys"
@menu-item-click="handleClickMenu"
>
<menu-item v-for="menu in menus" :key="menu.path" :menu="menu"></menu-item>
</a-menu>
</a-layout-sider>
<a-layout>
<a-layout-header>
<div></div>
</a-layout-header>
<a-layout-content class="content">
<div id="SubappViewportWrapper">
<div id="SubappViewport">
<div>
<!-- 模拟主应用中的三层结构 -->
<RouteView></RouteView>
</div>
</div>
</div>
</a-layout-content>
</a-layout>
</a-layout>
</template>
<script lang="ts" setup>
import { ref, watch, onMounted, computed, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
import store from '@/store'
import MenuItem from './MenuItem.vue'
import RouteView from './RouteView.vue'
const router = useRouter()
const menus = router.options.routes[0].children || []
const handleClickMenu = (key: string) => {
router.push({
name: key
})
}
</script>
<style lang="less" scoped>
.container {
height: 100vh;
}
.arco-layout-header {
display: flex;
justify-content: space-between;
align-items: center;
height: 72px;
background-color: #435279;
}
.logo {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 72px;
}
</style>
里面使用到的Route.vue
和主应用中用到的是一样的,代码就不贴出来了,可以到上一篇去找。
大家终于相信我了
在我贴出了我的代码证据之后,众人才愿意相信我进去小黑屋是和领导讨论技术升级的方案。
还有就是解释一下为什么这么久才更新子应用模板,那是因为搞完了架构,要开始搞写业务了,忙忙忙。这才是技术升级最烦的地方---业务开发。
还有就是在上一篇文章中,很多掘友说能一个iframe
能搞定的事情,非要整这么复杂,根本没必要。
其实个人觉得,做项目的基础架构的时候,不能为了只考虑方便和现在,要考虑到之后的扩展,我觉得每个技术存在并且能被大家接受,还是有一定的意义的,但是所有的技术都是为了业务而存在 ,所以大家在考虑技术架构的时候,必要的还是以业务优先 ,不要为了用而用。(一点个人见解,勿喷)
最后,小杜祝大家新年快乐,事业步步高升,人人都玩帕鲁,可是你们不要成为帕鲁。