前言
以下操作,是续接之前 第四步 ——即:vite+vue3+ts+pinia+element-plus项目已完成搭建好,可以直接业务开发了
主应用技术栈:vue2+webpack+js
集成qiankun(微前端)
1、安装vite-plugin-qiankun
npm install vite-plugin-qiankun
2、vite.config.ts文件修改,代码如下:
import qiankun from 'vite-plugin-qiankun'
const packName = require('./package').name // 必须要指定当前子应用命名// 配置NG——这个是与后台、运维约定好的,做NG转发;即主应用地址+子应用base就会直接NG转发base: '/vitedemo',plugins: [// 配置qiankunqiankun(`${packName}`, {useDevMode: true}),...]
注意点:
本地启动测试主子应用切换需要在server:{}里面添加headers: {‘Access-Control-Allow-Origin’: ‘*’ }, 解决主应用跳子应用跨域问题
server: {headers: {'Access-Control-Allow-Origin': '*'},host: '0.0.0.0',port,open: true,https: false,...}
2、main.ts文件修改,完整代码如下:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
// 所有业务api接口
import api from './api'
/*** element-plus*/
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 因element-plus默认是英文,我们指定一下默认中文
import locale from 'element-plus/lib/locale/lang/zh-cn'
// 图标并进行全局注册
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
// pinia代替vuex
import pinia from './store'
// 权限控制(全局路由守卫)
import './permission'
/*** 样式*/
// 公共样式
import '@/assets/styles/index.scss'
// 初始化样式
import 'normalize.css'
// 统一注册 baseComponents
import baseComponentsInstall from '@/components/baseComponents/install'
// svg渲染
import SvgIcon from '@/components/SvgIcon/index.vue'
/*** 配置qiankun*/
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
let instance: any = null
function render(props: any = {}) {const { container } = propsinstance = createApp(App)instance.use(router)instance.use(pinia)// 注册全局api方法instance.config.globalProperties.$api = api// 注册所有图标for (const [key, component] of Object.entries(ElementPlusIconsVue)) {instance.component(key, component)}// 注册ElementPlusinstance.use(ElementPlus, {locale // 语言设置// size: Cookies.get('size') || 'medium' // 尺寸设置})// 自动注册全部本地组件instance.use(baseComponentsInstall)// 全局组件祖册instance.component('SvgIcon',// 如果这个组件选项是通过 `export default` 导出的,那么就会优先使用 `.default`,否则回退到使用模块的根SvgIcon.default || SvgIcon)instance?.mount(container ? container.querySelector('#app') : '#app')console.log('开始加载相关内容')
}
renderWithQiankun({mount(props: any) {render(props)},bootstrap() {console.log('%c', 'color:green;', ' ChildOne bootstrap')},update() {console.log('%c', 'color:green;', ' ChildOne update')},unmount(props: any) {console.log('unmount', props)instance.unmount()instance._container.innerHTML = ''instance = null}
})
if (!qiankunWindow.__POWERED_BY_QIANKUN__) {console.log('并不是qiankun渲染')render()
}
3、router.ts文件修改,完整代码如下:
import { createRouter, createWebHistory } from 'vue-router'
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
import Layout from '@/layout/index.vue'
import login from '@/views/login.vue'
export const constantRoutes: any = qiankunWindow.__POWERED_BY_QIANKUN__? [{path: '/login',name: 'login',component: login,hidden: true,meta: {rootPage: true,noCache: true}},{path: '/redirect',component: Layout,hidden: true,children: [{path: '/redirect/:path(.*)',component: () => import('@/views/redirect.vue')}]},{path: '',component: Layout,redirect: 'index',hidden: true,children: [{path: '/index',component: () => import('@/views/index.vue'),name: 'index',hidden: true,meta: { title: '首页', icon: 'monitor', noCache: true, affix: true }}]}]: [{path: '/redirect',component: Layout,hidden: true,children: [{path: '/redirect/:path(.*)',component: () => import('@/views/redirect.vue')}]},{path: '/login',component: login,hidden: true,meta: {noCache: true}},{path: '/404',component: () => import('@/views/error/404.vue'),hidden: true},{path: '/401',component: () => import('@/views/error/401.vue'),hidden: true},{path: '',component: Layout,redirect: 'index',hidden: true,children: [{path: '/index',component: () => import('@/views/index.vue'),name: 'index',hidden: true,meta: { title: '首页', icon: 'monitor', noCache: true, affix: true }}]}]const router = createRouter({history: createWebHistory(qiankunWindow.__POWERED_BY_QIANKUN__ ? '/' : '/vitedemo/'),routes: constantRoutes,
})
export default router
3、全局路由守卫permission.ts文件修改,完整代码如下:
import router from './router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/cookies'
import { ElMessage } from 'element-plus'
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
import useUserStore from '@/store/modules/user'
import usePermissionStore from '@/store/modules/permission'
NProgress.configure({ showSpinner: false })
const whiteList = ['/login']
router.beforeEach((to: any, from: any, next: Function) => {NProgress.start()if (getToken()) {if (to.path === '/login') {next({ path: '/' })NProgress.done()} else {if (usePermissionStore().sysMenu.length === 0) {// 路由信息是不是组装完useUserStore().GetInfo()usePermissionStore().generateRoutes().then((accessRoutes: any) => {accessRoutes.forEach((rout: any) => {router.addRoute(rout) // 动态添加可访问路由表})next({ ...to, replace: true })}).catch(err => {useUserStore().FedLogOut()ElMessage.error(err.message || err.msg || '出现错误,请稍后再试')next({ path: '/' })})} else {// 进入页面前设置菜单if (!qiankunWindow.__POWERED_BY_QIANKUN__) {// 子应用单独运行,直接进入该系统const add_routes = toRaw(usePermissionStore().sysMenu)if (to.path === '/index') {let lastChild =add_routes[0]?.children?.length > 0? add_routes[0].children[0]: add_routes[0]if (to.path === lastChild.path) return falsenext(lastChild)NProgress.done()} else {console.log('子项目的next')next()}} else {console.log('主应用进入')next()}}}} else {if (whiteList.indexOf(to.path) !== -1) {next()} else {next(`/login`)NProgress.done()}}
})
router.afterEach(() => {NProgress.done()
})
4、其他文件修改,如下:
5、到此子应用已经配置完成
主应用跳转到子应用
主应用技术栈: vue2+js+element-ui
1、main.js修改,代码如下:
因为子应用是接口获取的,无需在单个注册
import { registerMicroApps, start } from "qiankun";
// 获取所有子应用
import childrenApp from './children.json'
// console.log('clientType=B', res)
const res = childrenApp
if (res.code == 200) {if (window.__POWERED_BY_QIANKUN__) {__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;}console.log('获取所有子应用', res.data)const apps = res.data.children && res.data.children.map((item) => {return {name: item.packageName,// 微应用package.json的name字段entry: item.entry,// 微应用访问地址,默认加载这个html页面并解析其中的js动态执行container: '#app', // 容器名activeRule: item.activeRule,// 激活路径,微应用路由}})apps && registerMicroApps(apps, {beforeLoad: async (app) => {console.log('before load', app)document.title = 'vue3+vite+ts'},beforeMount: [async (app) => {console.log('before mount', app.name)}]})// 启动 qiankunstart()
} else {Element.Message.warning('加载微应用失败,将无法访问子系统')
}
new Vue({router,store,render: h => h(App)
}).$mount("#app")
2、最终效果
组件地址
gitHub组件地址
gitee码云组件地址
子应用在线预览地址
相关文章
基于ElementUi再次封装基础组件文档
vue3+ts基于Element-plus再次封装基础组件文档