子应用:
第一步:npm i single-spa-vue
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import singleSpaVue from 'single-spa-vue'
Vue.config.productionTip = false
const appOptions = {
el: '#vue', // 挂载到父应用的id为vue的标签中
router,
render: h => h(App)
}
const vueLifeCycle = singleSpaVue({
Vue,
appOptions
})
/* 如果是父应用引入,文件的路径要改变
window.singleSpaNavigate为true表示父应用引用了我
保证子应用当前的引用路径都是绝对路径,相对于自己的路径,而不是父类的。
*/
if (window.singleSpaNavigate) {
// eslint-disable-next-line no-undef
__webpack_public_path__ = 'http://localhost:10000/'
}
// 希望子应用独立运行
// 独立运行时不能再挂载到#vue上了,要挂载到id为app的标签中
if (!window.singleSpaNavigate) {
delete appOptions.el
// eslint-disable-next-line no-new
new Vue(appOptions).$mount('#app')
}
// 协议接入,父应用会调用这些方法
export const bootstrap = vueLifeCycle.bootstrap
export const mount = vueLifeCycle.mount
export const unmount = vueLifeCycle.unmount
vue.config.js
module.exports = {
configureWebpack: {
output: {
// 向window中注册singleVue
library: 'singleVue',
// eslint-disable-next-line no-dupe-keys
// 打包后的文件输出为umd格式
libraryTarget: 'umd'
},
devServer: {
port: 10000
}
}
}
router.js
为了正常显示,子应用中要虚拟一个路径,可以通过更改router的base属性,此时子应用在启动时会自动的以/vue为基准加载。
new VueRouter({
mode: 'history',
base: '/vue',
routes
})
父应用
第一步:npm i single-spa
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { registerApplication, start } from 'single-spa'
async function loadScript (url) {
console.log(url)
return new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.onload = resolve
script.onerror = reject
document.head.appendChild(script)
})
}
// 先注册一个应用,当条件满足时会加载另外一个应用的包(手动通过创建script标签去加载),加载好了以后子应用打包出来时会有bootStarp mount unmout供父应用调用
// 调mount方法时会走子应用的注册vue方法(appOptions),将子应用挂载到父应用的vue标签内
registerApplication(
'myVueApp',
async () => {
await loadScript('http://localhost:10000/js/chunk-vendors.js')
await loadScript('http://localhost:10000/js/app.js')
return window.singleVue // bootStarp mount unmout
},
// 应用切换到/vue的路径下,需要加载刚定义的子应用
location => location.pathname.startsWith('/vue')
// 可以通过props进行父子通信
// props: {}
)
start()
// customElements事件可以进行父子应用的通信
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
App.vue
新建一个id为vue的div,让子应用挂载
<template>
<div id="app">
<router-link to="/vue">加载vue应用</router-link>
<!-- 子应用加载的位置 -->
<div id="vue"></div>
</div>
</template>
缺陷:
不够灵活,不能动态加载js文件
样式未隔离 没有js沙盒的机制