qiankun 结合 vue3, 小白快速上手体验

一、主应用改造

首先需要维护一份微应用列表,里面包含了微应用的名称、入口和生效规则,若需要给子应用传递内容,可以在 props 传入对应的内容

javascript 复制代码
// app.js
const apps = [
  {
    name: 'micro-vue-app3',
    entry: '//localhost:3013',
    container: '#micro-vue-app3',
    activeRule: '/micro-vue3-app3',
    props: {},
  },
]

export default apps

有了微应用数据后,我们就开始注册微应用

javascript 复制代码
// micro.js

import { registerMicroApps, addGlobalUncaughtErrorHandler, start } from "qiankun"

import apps from "./app"

/** 注册微应用 */
registerMicroApps(apps, {
	// 微应用加载前
	beforeLoad: (app) => {
		console.log("before-load", app.name)
		return Promise.resolve()
	},
	beforeMount: (app) => {
		console.log("before mount", app)
		return Promise.resolve()
	},
	afterMount: (app) => {
		console.log("after mount", app.name)
		return Promise.resolve()
	}
})

addGlobalUncaughtErrorHandler((event: Event | string) => {
	console.error(event)
	const { message: msg } = event as any
	if (msg && msg.includes("died in status LOADING_SOURCE_CODE")) {
		console.error("微应用加载失败,请检查应用是否可运行")
	}
})

export default start

接下来,我们在项目的入口文件中启动微前端。

js 复制代码
import { createApp } from 'vue'
import router from './router'
import startQiankun from './micro'
import App from './App.vue'

// start()
startQiankun({
  sandbox: {
    experimentalStyleIsolation: true, // 样式隔离
  },
})

const app = createApp(App)
app.use(router)

app.mount('#app')

二、子应用改造

vue3 项目创建方式分为 vue-cli 创建和 vite 创建,vue-cli 底层是 webpack,两种方式创建的项目的改造内容不太一样,接下来便为各位介绍一下改造点。

vue-cli 创建 vue3 子应用

vue.config.js 配置,需要将输出文件格式改成 umd 库格式

javascript 复制代码
const { defineConfig } = require('@vue/cli-service')
const { name } = require('./package.json')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer: {
    port: 3013,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
    },
  },
})

创建 public-path.ts文件,动态设置 webpack publicPath 防止资源报错

javascript 复制代码
if (window.__POWERED_BY_QIANKUN__) {
  // 动态设置 webpack publicPath,防止资源加载出错
  // eslint-disable-next-line no-undef
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__
}

main.js需要区分独立运行还是子应用运行

javascript 复制代码
import './public-path'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

let instance = null

function render(props = {}) {
  const { container } = props
  instance = createApp(App)
  instance.use(router)
  instance.use(store)
  instance.mount(container ? container.querySelector('#app') : '#app')
}

// 非乾坤环境
if (!window.__POWERED_BY_QIANKUN__) {
  render()
}
export async function bootstrap() {
  console.log('初次注册================')
  console.log('[vue] vue app bootstraped')
}

export async function mount(props) {
  console.log('挂载子应用==============vue3-app')
  console.log(props)
  render(props)
  instance.config.globalProperties.$onGlobalStateChange = props.onGlobalStateChange
  instance.config.globalProperties.$setGlobalState = props.setGlobalState
}

export async function unmount() {
  console.log('子应用卸载==========')
  instance.unmount()
  instance._container.innerHTML = ''
  instance = null
}

vite 创建 vue3 子应用

vite 若要用在 qiankun 微前端,需要安装 vite-plugin-qiankun 插件支持,并修改 vite.confit.ts配置:

javascript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import qiankun from 'vite-plugin-qiankun'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    qiankun('vite-vue3-app3', {
      useDevMode: true,
    }),
  ],
  server: {
    port: 7001,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
})

main.ts文件中,需要引入 renderWithQiankunqiankunWindow

javascript 复制代码
// @ts-nocheck
import { createApp } from 'vue'
import router from './router'
import App from './App.vue'
import actions from './shared/action'
import { renderWithQiankun, qiankunWindow } from 'vite-plugin-qiankun/dist/helper'

let app

function render(props) {
  if (props) {
    // 注入 actions 实例
    actions.setActions(props)
  }
  const { container } = props
  app = createApp(App)
  app.use(router)
  app.mount(container ? container.querySelector('#app') : '#app')
}

const initQianKun = () => {
  renderWithQiankun({
    /**
     * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
     */
    mount(props) {
      console.log('vite 应用挂载', props)
      const { container } = props
      render(props)
    },
    /**
     * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
     * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
     */
    bootstrap() {
      console.log('vite-vue3 初始化')
    },
    /**
     * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
     */
    unmount() {
      console.log('vite-vue3 卸载')
      app.unmount()
    },
  })
}

qiankunWindow.__POWERED_BY_QIANKUN__ ? initQianKun() : render()

router路由的 window 对象也需要用 qiankunWindow 去替换:

typescript 复制代码
import { createRouter, RouteRecordRaw, createWebHistory } from 'vue-router'
import { qiankunWindow } from 'vite-plugin-qiankun/dist/helper'
import HelloWorld from '../components/HelloWorld.vue'
import Text from '../components/Text.vue'

const routes: Array<RouteRecordRaw> = [{ path: '/', name: 'Home', component: HelloWorld, children: [{ path: 'text', name: 'Text', component: Text }] }]
const base = qiankunWindow.__POWERED_BY_QIANKUN__ ? '/vite-vue3-app3' : '/'

const router = createRouter({
  history: createWebHistory(base),
  routes,
})

export default router

三、Actions 通信

qiankun 内部提供了 initGlobalState 方法用于注册 MicroAppStateActions 实例用于通信,该实例有三个方法,分别是:

  • setGlobalState:设置 globalState - 设置新的值时,内部将执行 浅检查,如果检查到 globalState 发生改变则触发通知,通知到所有的 观察者 函数。
  • onGlobalStateChange:注册 观察者 函数 - 响应 globalState 变化,在 globalState 发生改变时触发该 观察者 函数。
  • offGlobalStateChange:取消 观察者 函数 - 该实例不再响应 globalState 变化。
js 复制代码
import { initGlobalState, MicroAppStateActions } from 'qiankun'

const initialState = {}
const actions = initGlobalState(initialState)

const actions = actions.setGlobalState({
  userInfo: { name: '改变用户', ssga: '2515' },
  age: ++currentAge.value,
})

// onGlobalStateChange 第二个参数为 true,表示立即执行一次观察者函数
actions.onGlobalStateChange((state) => {
  console.log(state, 'state')
  const { userInfo, age } = state
  currUserInfo.value = userInfo
  currentAge.value = age
}, true)

四、总结

本文介绍了 vue3 接入 qiankun 的方法,希望有助于个人初次上手了解。也有些人认为 vue3 结合 vite 的话,使用无界的方法会更好,有时间也会去看看如何使用,欢迎各位友好交流讨论!

相关推荐
万少17 分钟前
第五款 HarmonyOS 上架作品 奇趣故事匣 来了
前端·harmonyos·客户端
OpenGL23 分钟前
Android targetSdkVersion升级至35(Android15)相关问题
前端
rzl0239 分钟前
java web5(黑马)
java·开发语言·前端
Amy.Wang40 分钟前
前端如何实现电子签名
前端·javascript·html5
海天胜景42 分钟前
vue3 el-table 行筛选 设置为单选
javascript·vue.js·elementui
今天又在摸鱼43 分钟前
Vue3-组件化-Vue核心思想之一
前端·javascript·vue.js
蓝婷儿44 分钟前
每天一个前端小知识 Day 21 - 浏览器兼容性与 Polyfill 策略
前端
百锦再1 小时前
Vue中对象赋值问题:对象引用被保留,仅部分属性被覆盖
前端·javascript·vue.js·vue·web·reactive·ref
jingling5551 小时前
面试版-前端开发核心知识
开发语言·前端·javascript·vue.js·面试·前端框架
拾光拾趣录1 小时前
CSS 深入解析:提升网页样式技巧与常见问题解决方案
前端·css