本文小编为大家详细介绍“微前端qiankun改造实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“微前端qiankun改造实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
改造过程
首先我先用vue2-admin-cli——我自己做的脚手架工具,创建两个vue-admin项目来演示,一个作为qiankun基座,另外一个就是我要引用的子应用。
全局安装脚手架npm install -g vue2-admin-cli # oryarn global add vue2-admin-cli创建项目vue2-admin-cli init <project_name>安装依赖yarn启动项目yarn serve
运行起来就是这样的
现在我们开始分别改造基座qiankun-base和子应用qiankun-vue,我想达到的效果是主应用qiankun-base只保留header sider footer的一个基本layout的布局,content部分全部加载子应用
qiankun-base
yarn add qiankun # 或者 npm i qiankun -S修改package.json启动命令修改启动端口"serve": "vue-cli-service serve --port 80 --open"src/router/index.ts修改路由模式为history const createRouter = () => new VueRouter({ mode: "history", routes: routes as any, });修改vue.config.js 我这里之前用的路由模式是hash 上线配置了publicPath 导致改为history以后静态资源加载路径有问题所以修改module.exports = { // publicPath: "./", devServer: { disableHostCheck: true, // 关闭host检查 },};
在入口文件src/main.ts下注册微应用并启动:
import { registerMicroApps, start } from "qiankun";registerMicroApps([ { name: "qiankunVue", entry: "//localhost:8080", 子应用的启动端口修改为8080,基座使用80,不要相同 container: "#qiankunVue", 加载子应用的容器 activeRule: "/qiankunVue", 路由匹配规则 },]);// 启动 qiankunstart();
在你要放置子应用的位置增加一个容器用于加载子应用
src/components/layout/index.vue
<template> <el-container direction="vertical" > <Header /> <el-container > <el-aside width="250px"> <Menu /> </el-aside> <el-main> <el-breadcrumb separator-class="el-icon-arrow-right" v-if="showBreadcrumb" > <template v-for="(route, index) in matchedRoutes"> <el-breadcrumb-item v-if=" (route.meta && route.meta.breadcrumbTo === false) || index === matchedRoutes.length - 1 " :key="route.path" > {{ route.meta.title }} </el-breadcrumb-item> <el-breadcrumb-item v-else :key="route.path" :to="{ path: route.path }" > {{ route.meta.title }} </el-breadcrumb-item> </template> </el-breadcrumb> <!-- 本身的路由加载 --> <router-view /> <!-- 子应用加载容器 --> <div id="qiankunVue" /> </el-main> </el-container> </el-container></template>
将主应用之前的路由配置进行修改,不渲染自己的内容了,因为要改成去加载子应用的内容才是我们想要的,我的左侧菜单栏sider也是用路由配置这份文件生成的,所以我只需要注释这些路由要渲染的components就行,让他只充当一个生成sider菜单栏的作用,但是注意要保留容器所在的layout,因为我的子应用加载容器在这里面,加载子应用之前你必须保证容器被加载了
src/router/config.ts
const routes: Array<IBaseRouter> = [ { path: "/", redirect: "/home", hidden: true, }, { path: "/login", name: "login", hidden: true, component: () => import("../views/Login.vue"), }, //保证子应用加载时容器页面必须加载 { path: "/qiankunVue/*", name: "qiankunVue", hidden: true, component: Layout, }, { path: "/qiankunVue/home", name: "home", component: Layout, redirect: "/qiankunVue/home/index", meta: { title: "首页", icon: "el-icon-s-home", }, children: [ { path: "index", name: "index", hidden: true, // component: () => import("../views/Home.vue"), meta: { title: "首页", breadcrumb: false, }, }, { path: "bar/:width/:height", name: "bar", props: true, hidden: true, // component: () => import("@/components/echarts/Bar.vue"), meta: { title: "柱状图", activeMenu: "/home/index", }, }, { path: "pie/:width/:height", name: "pie", props: true, hidden: true, // component: () => import("@/components/echarts/Pie.vue"), meta: { title: "饼图", activeMenu: "/home/index", }, }, { path: "line/:width/:height", name: "line", props: true, hidden: true, // component: () => import("@/components/echarts/Line.vue"), meta: { title: "折线图", activeMenu: "/home/index", }, }, ], }, ..... { path: "*", redirect: "/error/404", hidden: true, },];export default routes;
改完之后刷新看一看,这样基座项目就改造好了,保留了基本页面的框架,中间的内容到时候都由子应用来填充就行了
qiankun-vue
修改package.json启动命令修改启动端口
"serve": "vue-cli-service serve --port 8080 --open"
入口文件 src/main.ts 修改
let vm: any = null;function render(props: any = {}) { const { container } = props; vm = new Vue({ router, store, render: (h) => h(App), }).$mount(container ? container.querySelector("#app") : "#app");}// 在被qiankun引用时 修改运行时的 `publicPath`if ((window as any).__POWERED_BY_QIANKUN__) { __webpack_public_path__ = (window as any).__INJECTED_PUBLIC_PATH_BY_QIANKUN__;}// 独立运行时if (!(window as any).__POWERED_BY_QIANKUN__) { render();}导出三个生命周期函数export async function bootstrap() { console.log("[vue] vue app bootstraped");}export async function mount(props: any) { console.log("[vue] props from main framework", props); render(props);}export async function unmount() { vm.$destroy(); vm.$el.innerHTML = ""; vm = null;}export default vm;
src/router/index.ts修改路由模式并增加base(和主应用设置的activeRule一致)
const createRouter = () => new VueRouter({ mode: "history", base: "/qiankunVue", routes: routes as any });
打包配置修改(`vue.config.js`)
module.exports = { devServer: { disableHostCheck: true, // 关闭host检查 headers: { "Access-Control-Allow-Origin": "*", // 防止加载时跨域 }, }, configureWebpack: { output: { library: "qiankunVue", libraryTarget: "umd", // 把微应用打包成 umd 库格式 }, },};
基座和子应用都修改完以后刷新看看,控制台报错了
立马查看官方文档,发现是因为我的子应用加载容器在基座的某个路由页面即我的layout里面,文档里指出必须保证微应用加载时主应用这个路由页面也加载了,就很喜欢这种文档????????,于是立马改一改
注释之前qiankun-base注册子应用时的启动qiankun命令,改到路由页面layout里面启动
src/main.ts
// 启动 qiankun//start();src/components/layout/index.vueimport { start } from "qiankun"; mounted() { if (!(window as any).qiankunStarted) { (window as any).qiankunStarted = true; start(); } }
重新刷新看看,成功了????????,多少有点舒服了
接下来要做的就是把子应用再改造一下,在qiankun中就只需要展示子应用content的内容,单独运行的时候为了方便调试我们就保留layout布局。看了这么久的官方文档,我当然知道用它就可以做出判断__POWERED_BY_QIANKUN__,思路很清晰,冲他????????
qiankun-vue
src/components/layout/index.vue
<template> <el-container direction="vertical" v-if="isQiankun"> <el-main> <el-breadcrumb separator-class="el-icon-arrow-right" v-if="showBreadcrumb" > <template v-for="(route, index) in matchedRoutes"> <el-breadcrumb-item v-if=" (route.meta && route.meta.breadcrumbTo === false) || index === matchedRoutes.length - 1 " :key="route.path" > {{ route.meta.title }} <!-- {{ route.path }} --> </el-breadcrumb-item> <el-breadcrumb-item v-else :key="route.path" :to="{ path: route.path }" > {{ route.meta.title }} <!-- {{ route.path }} --> </el-breadcrumb-item> </template> </el-breadcrumb> <router-view /> </el-main> </el-container> <el-container direction="vertical" v-else> <Header /> <el-container > <el-aside width="250px"> <Menu /> </el-aside> <el-main> <el-breadcrumb separator-class="el-icon-arrow-right" v-if="showBreadcrumb" > <template v-for="(route, index) in matchedRoutes"> <el-breadcrumb-item v-if=" (route.meta && route.meta.breadcrumbTo === false) || index === matchedRoutes.length - 1 " :key="route.path" > {{ route.meta.title }} <!-- {{ route.path }} --> </el-breadcrumb-item> <el-breadcrumb-item v-else :key="route.path" :to="{ path: route.path }" > {{ route.meta.title }} <!-- {{ route.path }} --> </el-breadcrumb-item> </template> </el-breadcrumb> <router-view /> </el-main> </el-container> </el-container></template><script lang="ts">import { Vue, Component } from "vue-property-decorator";import Header from "./Header.vue";import Menu from "./Menu.vue";// import { IBaseRouter } from "@/router/config";@Component({ name: "Layout", components: { Header, Menu },})export default class Layout extends Vue { private get showBreadcrumb() { return this.$route?.meta?.breadcrumbAll !== false; } private get matchedRoutes() { return this.$route.matched?.filter( (v) => v.meta?.title && v?.meta?.breadcrumb !== false ); } private get isQiankun() { return (window as any).__POWERED_BY_QIANKUN__; }}</script><style lang="less" scoped></style>
看看效果 基座正常展示子应用
子应用单独运行也正常展示,并且丝毫不影响开发体验
读到这里,这篇“微前端qiankun改造实例分析”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网行业资讯频道。