Qiankun-(一)基于若依框架集成其他vue子项目

777 阅读3分钟

一、主框架若依配置

1.若依框架内安装qiankun

  npm install qiankun

2.配置 main.js

// 引入
import { registerMicroApps, start, setDefaultMountApp } from 'qiankun'

// Step1 定义对应的微前端应用
const apps = [
  {
    name: 'subApp',
    entry: '//localhost:8201', // 子应用实际启动地址
    container: '#subApp-viewport',// 子应用在主应用展示容器的id
    activeRule: '/subApp' // 引入子应用的路由地址
  }, {
    name: 'subApp2',
    entry: '//localhost:8080', // 子应用实际启动地址
    container: '#subApp2-viewport',// 子应用在主应用展示容器的id
    activeRule: '/subApp2' // 引入子应用的路由地址
  }
]

// Step2 注册
registerMicroApps(apps, {
  beforeLoad: [
    (app) => {
      console.log(`${app.name}${app.entry}的beforeLoad阶段`)
    }
  ],
  beforeMount: [
    (app) => {
      console.log(`${app.name}的beforeMount阶段`)
    }
  ],
  afterMount: [
    (app) => {
      console.log(`${app.name}的afterMount阶段`)
    }
  ],
  beforeUnmount: [
    (app) => {
      console.log(`${app.name}的beforeUnmount阶段`)
    }
  ],
  afterUnmount: [
    (app) => {
      console.log(`${app.name}的afterUnmount阶段`)
    }
  ]
})

// Step3 设置默认进入的子应用
setDefaultMountApp('/subApp');

// Step4 启动应用
start()

3.配置App.vue

# 添加应用容器
<template>
  <div id="app">
    <router-view/>
    <div class="subApp" id="subApp-viewport"></div>
    <div class="subApp" id="subApp2-viewport"></div>
  </div>
</template>

4. vue.config.js里面允许跨域

# 允许跨域访问子应用页面
 headers: {
    'Access-Control-Allow-Origin': '*'
 },
 
#添加代理子应用的服务
 proxy: {
      // 微应用的代理
      '/mg': {
        target: 'http://localhost:5222', // 本地服务器
        changeOrigin: true,
        pathRewrite: {
          '^/mg': ''
        }
        // logLevel:'debug' // 打印代理以后的地址
      },
      '/req_ip': {
        target: 'http://pv.sohu.com', // 获取Ip地址
        changeOrigin: true,
        pathRewrite: {
          '^/req_ip': ''
        }
      },
      ['/subApp' + process.env.VUE_APP_BASE_API]: {
        target: `http://localhost:8080`, // 调用后端服务的地址
        changeOrigin: true,
        logLevel: 'debug',// 可以在控制台中看到调用接口代理后的真实地址
        pathRewrite: {
          ['^/subApp' + process.env.VUE_APP_BASE_API]: ''
        }
      },
      // 主应用的代理
      // detail: https://cli.vuejs.org/config/#devserver-proxy
      [process.env.VUE_APP_BASE_API]: {
        target: `http://localhost:8080`,
        changeOrigin: true,
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      }
    },
    disableHostCheck: true
  },

二、微应用配置

1.src目录下添加 public-path.js

if (window.__POWERED_BY_QIANKUN__) {
  __webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}

2.配置main.js

// 引入 public-path.js
import "./public-path";

// 定义render方法
let instance = null;
function render(props = {}) {
  const { container } = props;
  instance = new Vue({
    router,
    store,
    render: (h) => h(App),
  }).$mount(container ? container.querySelector("#app") : "#app");
}

// 独立运行时
if (!window.__POWERED_BY_QIANKUN__) {
  render();
}

// bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap
export async function bootstrap() {
  console.log("[vue] vue app bootstraped");
}
export async function mount(props) {
  console.log("[vue] props from main framework", props);
  render(props);
}
export async function unmount() {
  instance.$destroy();
  instance.$el.innerHTML = "";
  instance = null;
}

3.重写router的base路径

const router = new VueRouter({
  base: window.__POWERED_BY_QIANKUN__ ? `/subApp` : "/",
  mode: "history",
  // base: process.env.BASE_URL,
  routes,
});

4.配置vue.config.js

// 允许跨域
devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*'
    }
}
// 配置输出
output = {
  libraryTarget: 'umd', // 或 'commonjs2'
  library: 'MyLibrary',// 设置库的名称
}

// 如果是webpack用
const name = "cesium管理系统"; // 网页标题
module.exports = {
  output: {
    library: `${name}-[name]`,
    libraryTarget: 'umd',
    jsonpFunction: `webpackJsonp_${name}`,
  },
};

三、主应用与子应用之间的通信

1. props传值

  // 主应用定义props
  {
    name: 'subApp2',
    entry: '//localhost:8080', // 子应用实际启动地址
    container: '#subApp2-viewport',// 子应用在主应用展示容器的id
    activeRule: '/subApp2', // 引入子应用的路由地址
    props: {
      // 传递给子应用的数据
      data: { key: 'value' },
      // 传递给子应用的方法
      parentFunction: () => {
        console.log('This function is from the parent app')
      }
    }
  }
  // 子应用 在main.js mount 方法中获取props
  export async function mount (props) {
    console.log('[vue] props from main framework', props)
    render(props)
    props.parentFunction()
  }

2.自定义事件

// 创建一个自定义事件
const customEvent = new CustomEvent('eventName', {
  detail: {
    message: '这是自定义事件的内容',
    time: new Date()
  }
})
// 触发自定义事件
window.dispatchEvent(customEvent)

// 接收事件
window.addEventListener('eventName', (e) => {
  console.log(e.detail);
});

3.Vuex 或者简单的全局变量,结合观察者模式

// 在主应用中设置
window.globalState = { key: 'value' };

// 在微应用中获取
console.log(window.globalState.key); // 'value'

4.initGloabalState全局状态管理对象

// 主应用使用
import { initGlobalState } from 'qiankun';


const initialState = { user: null }; // 设置初始状态
const actions = initGlobalState(initialState);


// 方法用于更新状态
actions.onGlobalStateChange((state, prev) => {
  console.log('主应用状态变化:', state, prev);
});


// 可以在需要的地方更新状态
actions.setGlobalState({
  user: { name: 'Alice' },
});

// 子应用使用
import { initGlobalState } from 'qiankun';


const actions = initGlobalState(); // 使用相同的初始化方式


// 监听全局状态变化
actions.onGlobalStateChange((state, prev) => {
  console.log('子应用接收到状态变化:', state, prev);
});


// 获取全局状态
const globalState = actions.getGlobalState();
console.log('当前全局状态:', globalState);


// 更新全局状态
actions.setGlobalState({
  user: { name: 'Bob' },
});
  • 确保子应用在被加载时能够正确访问到已初始化的全局状态。
  • 状态更新会在所有监听该状态的应用中同步。
  • 适度使用全局状态,以避免不必要的复杂度和性能问题。

5.Local Storage / Session Storage

// 主应用设置
localStorage.setItem('key', 'value');

// 微应用获取
console.log(localStorage.getItem('key')); // 'value'