qiankun單個(gè)微應(yīng)用集成的demo
這里改造的主應(yīng)用和微應(yīng)用都是Vue的項(xiàng)目,但是qiankun本身不限制技術(shù)棧枯途,不同子應(yīng)用可以是不同的技術(shù)棧愉舔,并且為了簡單,方便大家搭建锈嫩,這里的主微應(yīng)用全部都是利用Vue-cli腳手架生成的。
0改造主應(yīng)用
00創(chuàng)建微應(yīng)用容器
微應(yīng)用容器用于承載微應(yīng)用垦搬,渲染顯示微應(yīng)用
<!-- App.vue -->
<template>
<div id="appf">
<img src="./assets/logo.png">
<!-- <router-view/> -->
<hello-world/>
<div id='yourContainer'></div>
</div>
</template>
<script>
import HelloWorld from '@/components/HelloWorld.vue';
export default {
name: 'App',
components: { HelloWorld },
}
</script>
<!-- HelloWorld.vue -->
<router-link to="/chaiQiankunTest/ffff">
test1
</router-link>
<div @click="onChangePage('/chaiQiankunTest/ffff')" >test2</div>
//定義跳轉(zhuǎn)方法
onChangePage(url){
console.log(url)
this.routerGo(url, '我喜愛的男明星')
},
routerGo(href = '/', title = null, stateObj = {}) {
window.history.pushState(stateObj, title, href);
}
出于簡單考慮呼寸,這里沒有使用router-view,防止因?yàn)槁酚傻母淖兒锓。鲬?yīng)用的渲染出現(xiàn)變化对雪,現(xiàn)在這樣做方便微應(yīng)用掛載之后進(jìn)行對(duì)比。
01注冊微應(yīng)用
微應(yīng)用的注冊點(diǎn)可以自己選擇米绕,既可以在main.js中進(jìn)行注冊瑟捣,那么在應(yīng)用啟動(dòng)時(shí)就會(huì)執(zhí)行相應(yīng)的生命周期函數(shù)馋艺,還可以在路由守衛(wèi)中,命中路由之后進(jìn)行注冊迈套,demo中選擇在路由命中后動(dòng)態(tài)的注冊微應(yīng)用捐祠。
//router/index.js
import { registerMicroApps, start } from "qiankun"
router.beforeEach((to, from, next) => {
if (to.path.includes('/chaiQiankunTest/ffff')) {
registerMicroApps(
[
{
name: "chai-project",//這里的name一定要和微應(yīng)用這配置的output中的library相互對(duì)應(yīng),因?yàn)? name是主應(yīng)用找到微應(yīng)用對(duì)外暴露的生命周期函數(shù)的主要憑證
entry: "http://localhost:8080",//這是微應(yīng)用的入口地址
container: '#yourContainer',//這是在主應(yīng)用中微應(yīng)用的渲染承載容器
activeRule: "/chaiQiankunTest/ffff"http://這是進(jìn)行路由監(jiān)聽桑李,一旦匹配踱蛀,就會(huì)加載微應(yīng)用并進(jìn)行掛載,這里也要主要在微應(yīng)用中需要設(shè)置路由base的時(shí)候要相互對(duì)應(yīng)芙扎,后面會(huì)提到
}
],
{
beforeLoad: [
app => {
console.log("before load", app);
}
], // 掛載前回調(diào)
beforeMount: [
app => {
console.log("before mount", app);
}
], // 掛載后回調(diào)
afterUnmount: [
app => {
console.log("after unload", app);
}
] // 卸載后回調(diào)
}
)
start();
}
next();
})
01改造微應(yīng)用
00導(dǎo)出 qiankun
主應(yīng)用所需要的三個(gè)生命周期鉤子函數(shù)
這里主要修改的就是微應(yīng)用的入口文件main.js星岗,由于代碼不多,這里直接將整個(gè)文件代碼貼出來
//main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import routes from './router'
import axios from 'axios'
import Router from 'vue-router'
import './public-path'
let router = null;
let instance = null;
Vue.config.productionTip = false
Vue.use(Router);
/**
* 渲染函數(shù)
* 兩種情況:主應(yīng)用生命周期鉤子中運(yùn)行 / 微應(yīng)用單獨(dú)啟動(dòng)時(shí)運(yùn)行
*/
function render (props) {
// 在 render 中創(chuàng)建 VueRouter戒洼,可以保證在卸載微應(yīng)用時(shí)俏橘,移除 location 事件監(jiān)聽,防止事件污染
router = new Router({
// 運(yùn)行在主應(yīng)用中時(shí)圈浇,添加路由命名空間 /chaiQiankunTest/ffff,這和主應(yīng)用中注冊微應(yīng)用時(shí)的activeRule相互對(duì)應(yīng)
base: window.__POWERED_BY_QIANKUN__ ? 'chaiQiankunTest/ffff' : '/',
mode: 'history',
routes
});
// 掛載應(yīng)用
instance = new Vue({
router,
render: (h) => h(App),
beforeCreate () {
window.util = {}
window.util.$http = axios.create({
timeout: 1000 * 50,
withCredentials: true
})
}
}).$mount('#app');
}
// 獨(dú)立運(yùn)行時(shí)寥掐,直接掛載應(yīng)用
if (!window.__POWERED_BY_QIANKUN__) {
render();
}
/**
* bootstrap 只會(huì)在微應(yīng)用初始化的時(shí)候調(diào)用一次,下次微應(yīng)用重新進(jìn)入時(shí)會(huì)直接調(diào)用 mount 鉤子磷蜀,不會(huì)再重復(fù)觸發(fā) bootstrap召耘。
* 通常我們可以在這里做一些全局變量的初始化,比如不會(huì)在 unmount 階段被銷毀的應(yīng)用級(jí)別的緩存等褐隆。
*/
export async function bootstrap () {
console.log('mscrtApp bootstraped');
}
/**
* 應(yīng)用每次進(jìn)入都會(huì)調(diào)用 mount 方法污它,通常我們在這里觸發(fā)應(yīng)用的渲染方法
*/
export async function mount (props) {
console.log('mscrtApp mount', props);
render(props);
}
/**
* 應(yīng)用每次 切出/卸載 會(huì)調(diào)用的方法,通常在這里我們會(huì)卸載微應(yīng)用的應(yīng)用實(shí)例
*/
export async function unmount () {
console.log('mscrtApp unmount');
instance.$destroy();
instance = null;
router = null;
}
//public-path.js
if (window.__POWERED_BY_QIANKUN__) {
// 動(dòng)態(tài)設(shè)置 webpack publicPath庶弃,防止資源加載出錯(cuò)
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
這里面可能還牽扯到router/index.js的改造衫贬,將VueRouter的創(chuàng)建遷移到render中,具體的作用是可以保證在卸載微應(yīng)用時(shí)歇攻,移除 location 事件監(jiān)聽固惯,防止事件污染。
01配置 webpack
主要的目的是使 main.js
導(dǎo)出的生命周期鉤子函數(shù)可以被 qiankun
識(shí)別獲取 缴守。
//webpack.base.conf.js
output: {
// 微應(yīng)用的包名葬毫,這里與主應(yīng)用中注冊的微應(yīng)用名稱一致。這個(gè)名字也就是package.json中的name
library: 'chai-project',
// 將你的 library 暴露為所有的模塊定義下都可運(yùn)行的方式
libraryTarget: 'umd',
// 按需加載相關(guān)屡穗,設(shè)置為 webpackJsonp_VueMicroApp 即可
jsonpFunction: `webpackJsonp_chai-project`
},
//webpack.base.conf.js中的devServer對(duì)象中需要加入下面這個(gè)配置贴捡,這樣主應(yīng)用在fatch微應(yīng)用靜態(tài)資源時(shí)會(huì)出現(xiàn)跨域的問題
disableHostCheck: true,
headers: {
'Access-Control-Allow-Origin': '*'
}
如果沒有設(shè)置這個(gè)跨域的設(shè)置,那么就可能出現(xiàn)跨域問題村砂,
02demo演示
主應(yīng)用界面初始化
test1和test2是兩個(gè)觸發(fā)注冊微應(yīng)用的按鈕烂斋,功能一樣,點(diǎn)擊test1可以得到:
此時(shí)成功加載微應(yīng)用,并且DOM結(jié)構(gòu)為:
主應(yīng)用和微應(yīng)用的生命周期函數(shù)的執(zhí)行順序?yàn)?/p>
在點(diǎn)擊回退到主應(yīng)用的頁面之后源祈,主微應(yīng)用的生命周期鉤子函數(shù)的執(zhí)行順序?yàn)?/p>
總結(jié)
到這,Vue技術(shù)棧的主應(yīng)用和微應(yīng)用的集成Demo算是基本完成色迂,這里只是最基礎(chǔ)的一個(gè)集成示例香缺,它們的鉤子函數(shù)的執(zhí)行順序有些類似Vue中父子組件的生命周期函數(shù)的執(zhí)行順序。