前言
在 微前端MicroApp的学习(一):简单搭建项目 基础上继续学习微前端的其他内容。
功能
配置项
<micro-app></micro-app>
可以设置一些配置项,通过配置项可以决定开启或关闭某些功能。
常用配置项如下:
name
- Desc: 应用名称
- Type: string
- Default: 必传参数
- 使用方式:
<micro-app name='xx'></micro-app>
- 注意事项: 必须以字母开头,且不可以带有除中划线和下划线外的特殊符号
每个name都对应一个应用,当多个应用同时渲染时,name不可以重复。
当name的值发生变化时,会卸载当前应用并重新渲染。
url
- Desc: 应用地址
- Type: string
- Default: 必传参数
- 使用方式:
<micro-app name='xx' url='xx'></micro-app>
基座应用和子应用本质是在同一个页面,这里的url只是html地址,子应用的路由还是基于浏览器地址。
当url的值发生变化时,会卸载当前应用并根据新的url值重新渲染
baseroute
- Desc: 子应用的基础路由
- Type: string
- Default: ‘’
- 使用方式:
<micro-app name='xx' url='xx' baseroute='/my-page/'></micro-app>
在微前端环境下,子应用可以从window.__MICRO_APP_BASE_ROUTE__上获取baseroute的值,用于设置基础路由。
如果基座应用是history路由,子应用是hash路由,则不需要设置baseroute。
这里我们的应用是history路由,用不到这个
inline
- Desc: 是否使用内联script
- Default: false
- 使用方式:
<micro-app name='xx' url='xx' inline></micro-app>
默认情况下,子应用的js会被提取并在后台运行。
开启inline后,被提取的js会作为script标签插入应用中运行,在开发环境中更方便调试,会稍微损耗性能。
destroy
- Desc: 卸载时是否强制删除缓存资源
- Default: false
- 使用方式:
<micro-app name='xx' url='xx' destroy></micro-app>
默认情况下,子应用被卸载后会缓存静态资源,以便在重新渲染时获得更好的性能。
开启destroy,子应用在卸载后会清空缓存资源,再次渲染时重新请求数据。
disableScopecss
禁用样式隔离,不建议修改,禁用后可能会导致样式污染
keep-alive
- Desc: 是否开启keep-alive模式
- Type: string(boolean)
- Default: false
- 使用方式:
<micro-app name='xx' url='xx' keep-alive></micro-app>
- 版本要求: 0.6.0及以上版本
开启keep-alive后,应用卸载时会进入缓存,而不是销毁它们,以便保留应用的状态和提升重复渲染的性能。
keep-alive的优先级小于destroy,当两者同时存在时,keep-alive将失效。
shadowDOM
- Desc: 是否开启shadowDOM
- Type: string(boolean)
- Default: false
- 使用方式:
<micro-app name='xx' url='xx' shadowDOM></micro-app>
shadowDOM具有更强的样式隔离能力,开启后,标签会成为一个真正的WebComponent。
但shadowDOM在React框架及一些UI库中的兼容不是很好,经常会出现一些不可预料的问题,除非你很清楚它会带来的问题并有信心解决,否则不建议使用。
全局配置
全局配置会影响每一个子应用,使用如下:
import microApp from '@micro-zoe/micro-app'
microApp.start({
inline: true, // 默认值false
destroy: true, // 默认值false
disableScopecss: true, // 默认值false
disableSandbox: true, // 默认值false
shadowDOM: true, // 默认值false
ssr: true, // 默认值false
})
生命周期
生命周期列表
- created:
<micro-app>
标签初始化后,加载资源前触发。 - beforemount:加载资源完成后,开始渲染之前触发。
- mounted:子应用渲染结束后触发。
- unmount:子应用卸载时触发。
- error:子应用渲染出错时触发,只有会导致渲染终止的错误才会触发此生命周期。
监听生命周期
像vue监听普通事件一致,使用@
即可
<micro-app
name='xx'
url='xx'
@created='created'
@beforemount='beforemount'
@mounted='mounted'
@unmount='unmount'
@error='error'
/>
全局监听
全局监听会在每个应用的生命周期执行时都会触发。
使用:
import microApp from '@micro-zoe/micro-app'
microApp.start({
lifeCycles: {
created (e) {
console.log('created')
},
beforemount (e) {
console.log('beforemount')
},
mounted (e) {
console.log('mounted')
},
unmount (e) {
console.log('unmount')
},
error (e) {
console.log('error')
}
}
})
子应用卸载
对于子应用只有两个生命周期,挂载和卸载。
挂载:子应用的js被执行则为挂载,所以不需要特殊的监听,一般在入口js文件中进行挂载相关操作。
卸载:子应用被卸载时会接受到一个名为unmount的事件,开发者可以在此进行卸载相关操作。
// 子应用卸载
window.addEventListener('unmount', function () {
// 执行卸载相关操作
})
环境变量
MICRO_APP_ENVIRONMENT : 判断应用是否在微前端环境中
在子应用中通过 window.MICRO_APP_ENVIRONMENT 判断是否在微前端环境中。
if (window.__MICRO_APP_ENVIRONMENT__) {
console.log('我在微前端环境中')
}
MICRO_APP_NAME :在子应用中通过 window.MICRO_APP_NAME 获取应用的name值,即标签的name值。
MICRO_APP_PUBLIC_PATH :用于设置webpack动态public-path,将子应用的静态资源补全为 http 开头的绝对地址。 项目是用Vite
构建的,应该用不到,用到的话可以自行查看文档。
MICRO_APP_BASE_ROUTE:子应用的基础路由
MICRO_APP_BASE_APPLICATION:判断应用是否是基座应用,在执行microApp.start()
后此值才会生效
JS沙箱
目前用不到,暂不学习。
样式隔离
MicroApp的样式隔离是默认开启的,用默认配置就好,没必要修改。
元素隔离
暂时用不到
数据通信
正常情况下,基座应用和子应用之间的通信是绑定的,基座应用只能向指定的子应用发送数据,子应用只能向基座发送数据,这种方式可以有效的避免数据污染,防止多个子应用之间相互影响。
同时我们也提供了全局通信,方便跨应用之间的数据通信。
Tip
1、data只接受对象类型
2、数据变化时会进行严格对比(===),相同的data对象不会触发更新。
3、在子应用卸载时,子应用中所有的数据绑定函数会自动解绑,基座应用中的数据解绑需要开发者手动处理。
子应用获取来自基座应用的数据
micro-app会向子应用注入名称为microApp的全局对象,子应用通过这个对象和基座应用进行数据交互。
有两种方式获取来自基座应用的数据:
- 方式1:直接获取数据
- 方式2:绑定监听函数
这里直接用方式1比较简单
const data = window.microApp.getData() // 返回基座下发的data数据
子应用向基座应用发送数据
// dispatch只接受对象作为参数
window.microApp.dispatch({type: '子应用发送的数据'})
基座应用向子应用发送数据
- 通过data属性发送数据
<template>
<micro-app
name='my-app'
url='xx'
:data='dataForChild' // data只接受对象类型,数据变化时会重新发送
/>
</template>
<script>
export default {
data () {
return {
dataForChild: {type: '发送给子应用的数据'}
}
}
}
</script>
- 手动发送数据
手动发送数据需要通过name指定接受数据的子应用,此值和元素中的name一致。
import microApp from '@micro-zoe/micro-app'
// 发送数据给子应用 my-app,setData第二个参数只接受对象类型
microApp.setData('my-app', {type: '新的数据'})
基座应用获取来自子应用的数据
基座应用获取来自子应用的数据有三种方式:
直接获取数据、监听自定义事件、绑定监听函数
这里只学习前两种方式即可,比较简单
- 直接获取数据
import microApp from '@micro-zoe/micro-app'
const childData = microApp.getData(appName) // 返回子应用的data数据
- 监听自定义事件 (datachange)
<template>
<micro-app
name='my-app'
url='xx'
// 数据在事件对象的detail.data字段中,子应用每次发送数据都会触发datachange
@datachange='handleDataChange'
/>
</template>
<script>
export default {
methods: {
handleDataChange (e) {
console.log('来自子应用的数据:', e.detail.data)
}
}
}
</script>
全局数据通信
全局数据通信会向基座应用和所有子应用发送数据,在跨应用通信的场景中适用。
暂时不学习,感觉可以通过基座应用当中转站来实现子应用直接的通信。
关闭沙箱后的通信方式
沙箱关闭后,子应用默认的通信功能失效,此时可以通过手动注册通信对象实现一致的功能。
这个还是比较有用的,在上一篇文章中按照官方示例搭建项目就用到了这种通信,原因是:
因为vite子应用关闭了沙箱,我们需要为子应用appname-vite创建EventCenterForMicroApp对象来实现数据通信
- 注册方式:在基座应用中为子应用初始化通信对象
import { EventCenterForMicroApp } from '@micro-zoe/micro-app'
// 注意:每个子应用根据appName单独分配一个通信对象
window.eventCenterForAppxx = new EventCenterForMicroApp(appName)
子应用就可以通过注册的eventCenterForAppxx对象进行通信,其api和window.microApp一致,基座通信方式没有任何变化
- 子应用通信方式:
// 直接获取数据
const data = window.eventCenterForAppxx.getData() // 返回data数据
function dataListener (data) {
console.log('来自基座应用的数据', data)
}
/**
* 绑定监听函数
* dataListener: 绑定函数
* autoTrigger: 在初次绑定监听函数时如果有缓存数据,是否需要主动触发一次,默认为false
*/
window.eventCenterForAppxx.addDataListener(dataListener: Function, autoTrigger?: boolean)
// 解绑监听函数
window.eventCenterForAppxx.removeDataListener(dataListener: Function)
// 清空当前子应用的所有绑定函数(全局数据函数除外)
window.eventCenterForAppxx.clearDataListener()
// 子应用向基座应用发送数据,只接受对象作为参数
window.eventCenterForAppxx.dispatch({type: '子应用发送的数据'})
看一下之前搭建的项目可以发现:
在基座应用为子应用分配的路由对应的vue文件vite.vue
中,进行了注册
// @ts-ignore 因为vite子应用关闭了沙箱,我们需要为子应用appname-vite创建EventCenterForMicroApp对象来实现数据通信
window.eventCenterForAppNameVite = new EventCenterForMicroApp("appname-vite");
在子应用的main.ts
中处理了通信
静态资源
暂时不学习
预加载
暂时不学习
插件系统
暂时不学习
多层嵌套
暂时不学习,很少会用到,如果子应用要嵌套其他子应用那基本上就是项目的整体架构有问题。
keep-alive
暂时不学习
高级功能
暂时不学习
路由
微前端的渲染离不开路由,而路由配置是最容易出问题的地方。
路由类型约束
- 1、基座是hash路由,子应用也必须是hash路由
- 2、基座是history路由,子应用可以是hash或history路由
在上一篇文章中,按照官方示例,我们搭建的项目基座和子应用都是用的history
路由
其他内容略
应用之间的跳转
每个应用的路由实例都是不同的,应用的路由实例只能控制自身,无法影响其它应用,包括基座应用无法通过控制自身路由影响到子应用。
常见的问题如:开发者想通过基座应用的侧边栏跳转,从而控制子应用的页面,这其实是做不到的,只有子应用的路由实例可以控制自身的页面。
具体内容自行查看文章。
实际应用中感觉基座应用用来导航,就如同之前搭建的项目。在基座应用中创建一个.vue
文件,为子应用分配一个路由,当切换基座中的路由时跳转到子应用的首页里。
手把手
自行学习即可,上一篇文章中项目的搭建参考的是
在官方文档中,这篇文章最下面给出了一个案例。可以参考这个案例来自己搭建一个简单的微前端demo。
其他
略,当实际项目中用到时再学习。