使用qianjkun uniapp 主应用 集成 vue微应用

uniapp 主应用 集成 vue微应用

乾坤官方文档

主应用为uniapp

在主应用安装qiankun框架

bash 复制代码
yarn add qiankun 
#或者
npm install qiankun

因为我们需要动态传递数据,则使用loadMicroApp方法动态加载
pages/work/preview/index页面文件

javascript 复制代码
<template>
	<view class="preview-container">
		<view class="micro-wrap">
			<div id="micro-container"></div>
		</view>
	</view>
</template>

<script>
let microApp = null
import { loadMicroApp } from 'qiankun';
import { getInfo } from '@/api/login'
import actions from '../../../share/actions';
export default {
	components: {},
	data() {
		return {
			loading: false,
			previewId: 1
		}
	},
	async onLoad() {
		await this.init()
	},
	async onUnload() {
		if (microApp) {
			await microApp.unmount()
			microApp = null
		}
	},
	methods: {
		async init() {
			this.loading = true
			actions.setGlobalState({
				previewId: this.previewId
			})
			await this.mountSub()
		},
		async mountSub() {
			const resp = await getInfo();
			// 获取系统信息
			const systemInfo = uni.getSystemInfoSync();
			microApp = loadMicroApp({
				name: 'test',
				entry: 'http://localhost/', //不要写路由 hash
				container: '#micro-container',
				props: {
					userInfo: resp.data,
					systemInfo,
					onGlobalStateChange: actions.onGlobalStateChange,
					setGlobalState: actions.setGlobalState
				},
				sandbox: {
					experimentalStyleIsolation: true //强制性的样式沙箱隔离
				}
			})
			await microApp.mountPromise
			this.loading = false

		}
	}
}
</script>

<style scoped>
.micro-wrap {
	overflow: hidden;
	height: calc(100vh - 44px);
	width: 100%;
}
</style>

share/actions.js文件

javascript 复制代码
import {
	initGlobalState
} from 'qiankun';

// 主应用中注册全局事件
// 设置全局状态
const initialState = {
	currentTab: 0,
	zoomScale: 1,
	mobile: true
};
// 创建全局状态实例并导出
const actions = initGlobalState(initialState);
// 监听全局状态变化(可选)
 actions.onGlobalStateChange((newState, prev) => {
   console.log('主应用监听到全局状态变化:', newState, prev);
 });
export default actions;

微应用

1.在 src 目录新增 public-path.js

javascript 复制代码
if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

2.入口文件 main.js 修改,为了避免根 id #app 与其他的 DOM 冲突,需要限制查找范围。

javascript 复制代码
import './public-path'; // 需要放在第一行,不然icon图标会显示不出不来
import store from './store'
import { isMobile } from '@/utils'
let instance = null
/** ================微前端配置================ */
// 如果是在乾坤里面加载,则子应用应该跳过默认的加载逻辑,让主应用来控制当前应用的加载(匹配到子应用的路由标识)
if (!window.__POWERED_BY_QIANKUN__) {
  render({});
}
function render(props = {}) {
  const { container, userInfo, systemInfo } = props
  if (userInfo) {
    store.dispatch('setUserInfo', userInfo)
  }
  if (systemInfo) {
   // 手机样式
    if (isMobile(systemInfo.ua)) {
      document.body.classList.add('ua-mobile');
    } else {
      document.body.classList.add('ua-pc');
    }

  }

  // 监听主应用推过来的全局状态(true = 首次立即触发一次)
  props.onGlobalStateChange && props.onGlobalStateChange((state, prev) => {
    //更新 vuex / 组件状态 / 重新拉数据等
    store.dispatch('qiankun/setQkState', state)
  }, true) // true 表示进来就触发一次
  // 子应用也可以反向通知主应用
  // props.setGlobalState && props.setGlobalState({ childReady: true })
  instance = new Vue({
    el: container ? container.querySelector('#app') : '#app',
    router,
    store,
    render: h => h(App)
  })
}

// qiankun 生命周期
export async function bootstrap() {
  console.log('app bootstraped');
}
export async function mount(props) { render(props) }
export async function unmount() {
  instance.$destroy()
  instance.$el.innerHTML = ''
  instance = null
}

src\store\modules\qiankun.js状态文件

javascript 复制代码
const state = () => ({
    qiankunState: {}   // 主应用下发的全局状态
})
const mutations = {
    SET_QK_STATE(state, payload) {
        state.qiankunState = { ...state.qiankunState, ...payload }
    }
}
const actions = {
    setQkState({ commit }, payload) {
        commit('SET_QK_STATE', payload)
    }
}
export default { namespaced: true, state, mutations, actions }

监听状态变化,在vue文件里面加下下面的代码

javascript 复制代码
 computed: {
    ...mapState({
      // 箭头函数会使代码更简练
      currentTab: state => state.qiankun.qiankunState.currentTab,
      zoomScale: state => state.qiankun.qiankunState.zoomScale
    })
  },
  watch: {
    currentTab(newVal, oldVal) {
      conslole.log(newVal, oldVal)
    },
    zoomScale(newVal, oldVal) {
     conslole.log(newVal, oldVal)
    }
  },

3.打包配置修改(vue.config.js):

javascript 复制代码
const packageName = require('./package.json').name;
module.exports = {
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `${packageName}-[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      jsonpFunction: `webpackJsonp_${packageName}`, // webpack 5 需要把 jsonpFunction 替换成 chunkLoadingGlobal
    },
  },
};

4.新建路由

javascript 复制代码
{
    path: '/pages',
    component: Layout,
    hidden: true,
    redirect: 'noredirect',
    children: [{
      meta: {
        title: '微前端',
      },
      path: 'work/preview/index',
      // component: (resolve) => require(['@/views/hardware/manage/index'], resolve),
      component: (resolve) => require(['@/views/app/preview'], resolve),
      name: 'AppPreview',
      meta: {title: '微前端页面', icon: '', noCache: true}
    }]
  },

注意: 这里的路由地址需要与uniapppages/work/preview/index路径对应上

相关推荐
wc882 分钟前
微软EDGE浏览器功能学习
前端·学习·edge
Csvn35 分钟前
🎯 原生 `<dialog>` 元素:终于可以扔掉一半的自定义弹窗组件了?
前端
Csvn37 分钟前
🎨 CSS @layer:用「层叠优先级」终结样式打架的世纪难题
前端
小罗水1 小时前
第17章 后台管理端与演示支持
javascript·vue.js·ecmascript
濮水大叔1 小时前
不必把 Vue3 写成“麻花”:从状态碎片到对象协作,重新理解 Zova 的前端心智模型
前端·typescript·vue3·ioc·tsx·zova
Vuji2 小时前
MCP: 一条 tool 调用链路的旅程
前端·人工智能
万少3 小时前
DeepSeek-V4-Flash 正式版上线了,但这 3 个坑我帮你提前踩了
前端·javascript·后端
明月_清风3 小时前
🚀 Palantir Foundry 本体论实战:当 Ontology 从"知识图谱"进化为"企业操作系统"
前端·后端
驳是3 小时前
入坑 Nginx,看这一篇就够了
前端
宁风NF3 小时前
JavaScript:网络请求与前端通信
开发语言·前端·javascript·网络·学习·ecmascript