坚挺的打工人鼓捣qiankun(乾坤)随记

190 阅读2分钟

一路的搬砖心里历程,官方文档才是亲爸爸,so,官方的文档:qiankun.umijs.org/zh/guide/ge…

接触qiankun一开始直白的疑惑

1.主应用如何跳转子应用

2.子应用如何知道自己是在qiankun的环境中并且拿到主应用的登录信息等

3.子应用如何反向传递数据给主应用

<1.在主应用中注册微应用>

1.根据路由规则匹配注册应用 (url 发生变化自动触发 qiankun 的匹配逻辑,所有 activeRule 规则匹配上的微应用就会被插入到指定的 container 中,同时依次调用微应用暴露出的生命周期钩子)
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
  {
    name: 'app', // app name registered
    entry: '//localhost:7100',
    container: '#yourContainer',
    activeRule: '/yourActiveRule',
  },
  {
    name: 'vue app',
    entry: { scripts: ['//localhost:7100/main.js'] },
    container: '#yourContainer2',
    activeRule: '/yourActiveRule2',
  },
]);

start();

2.手动加载微应用
import { loadMicroApp } from 'qiankun';
loadMicroApp({
  name: 'app',
  entry: '//localhost:7100',
  container: '#yourContainer',
});

----------------------------------------注意点-----------------------------------------

entry:除了是本地之外,也可以直接服务器访问网址。
activeRule:注意路由base
container: 需在 APP.vue 中添加 `#yourContainer`  eg:<div id="yourContainer"></div>

主应用跳转:
this.$router.push({
  path: 'url'
})

子应用跳转主:
window.history.pushState(state, title, url); // state 数据(可选)title 标题(可选)url 路径 必填

<2.子应用改造>

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

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

2.入口文件 main.js 修改,为了避免根 id #app 与其他的 DOM 冲突

import './public-path';
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App.vue';
import routes from './router';
import store from './store';

Vue.config.productionTip = false;

let router = null;
let instance = null;
function render(props = {}) {
  const { container } = props;
  router = new VueRouter({
    base: window.__POWERED_BY_QIANKUN__ ? '/app-vue/' : '/',
    mode: 'history',
    routes,
  });

  instance = new Vue({
    router,
    store,
    render: (h) => h(App),
  }).$mount(container ? container.querySelector('#app') : '#app');
}

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

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;
  router = null;
}

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

const { name } = require('./package');
module.exports = {
  devServer: {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  configureWebpack: {
    output: {
      library: `${name}-[name]`,
      libraryTarget: 'umd', // 把微应用打包成 umd 库格式
      jsonpFunction: `webpackJsonp_${name}`,
    },
  },
};

<3.主应用及子应用传值>

1.父应用向子应用传递
<1.>注册路由时 props: {} 直接在子应用mount(props)拿到相关的传递的值
<2.>子应用在 `mount` 函数中接受 `props` 参数,通过 `onGlobalStateChange` 函数监听主应用传递过来的值
主:
import { initGlobalState } from 'qiankun'
let global = initGlobalState({isApp:''})
global.setGlobalState({isApp:true})

子:
props.onGlobalStateChange( state => {
    console.log('主应用数据',state)
}, true);

2.子应用向主应用传值
子:
props.setGlobalState({a:'我来了'})

父:
global.onGlobalStateChange(state => {
   // 监听全局状态,子应用更新主应用数据后触发
   console.log(state)
})

注意:一般不混乱增强可阅读性,增加单独管理actions.js
function emptyAction() {
  console.warn("action is empty!");
}
class Actions {
  actions = {
    onGlobalStateChange: emptyAction,
    setGlobalState: emptyAction,
  };
  setActions(actions) {
    this.actions = actions;
  }
  onGlobalStateChange(...args) {
    return this.actions.onGlobalStateChange(...args);
  }
  setGlobalState(...args) {
    return this.actions.setGlobalState(...args);
  }
}
const actions = new Actions();
export default actions;

尾记:解开了迷惑,qiankun也就处在了可上手状态,另外关于qiankun的js沙箱隔离,css样式隔离未尝试,希望有宝子能够指点一二