乾坤的vue入门小练习

382 阅读2分钟

因为项目主要是vue,就只练了vue,跟着这位大佬的文章练习的。

链接:juejin.cn/post/711379…

子应用创建

第一步:创建子应用sub-vue1,命令:vue create sub-vue1

第二步:将router修改为routes,里面代码改为


const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
  },
  {
    path: '/about',
    name: 'About',
    component: () =>
      import(/* webpackChunkName: "about" */ '../views/AboutView.vue'),
  },
];

export default routes;

第三步:在src文件夹下创建public-path.js文件,内容如下

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

第四步:修改main.js

import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import App from './App.vue';
import routes from './routes';
import store from './store';

let router = null;
let instance = null;

// 如果不是乾坤环境,直接运行render,从而让子应用可以独立运行
if (!window.__POWERED_BY_QIANKUN__) {
    render();
}

export async function bootstrap() {
    // 这个函数可以学学怎么用的,加个颜色
    console.log('%c ', 'color: green;', 'vue3.0 app bootstraped');
}

export async function mount(props) {
    render(props);
}

export async function unmount() {
    instance.unmount();
    instance._container.innerHTML = '';
    instance = null;
    router = null;
}


// todo: 在乾坤调用 render 函数的时候,会附上一些信息,比如说容器的挂载节点等
function render(props = {}) {
    const { container } = props;
    router = createRouter({
        // 如果是运行在乾坤的环境下,所有的路由路径会在开头加上/sub-vue
        history: createWebHistory(window.__POWERED_BY_QIANKUN__ ? '/sub-vue' : '/'),
        routes,
    });

    instance = createApp(App);
    instance.use(router);
    instance.use(store);
    instance.mount(container ? container.querySelector('#app') : '#app');
}

第五步:修改vue.config.js,按照文章里会有一些版本报错,应该是我的webpack5问题,所以按照提示注释一些属性,还有没研究,挖一个坑,后期补吧。

const { name } = require('./package');

function resolve(dir) {
  return path.join(__dirname, dir);
}

module.exports = {
  outputDir: 'dist',
  assetsDir: 'static',
  filenameHashing: true,
  devServer: {
    hot: true,
    // disableHostCheck: true,
    port: '8080',
    // overlay: {
    //   warnings: false,
    //   errors: true,
    // },
    // clientLogLevel: 'warning',
    compress: true,
    headers: {
      // 一定要加的,因为乾坤会用http的请求去获取子应用的代码,那么必然会出现跨域的问题。
      'Access-Control-Allow-Origin': '*',
    },
    historyApiFallback: true,
  },
  configureWebpack: {
    resolve: {
      alias: {
        '@': resolve('src'),
      },
    },
    output: {
      // 把子应用打包成 umd 库格式,从而主应用能够获取到子应用导出的生命周期钩子函数
      library: `${name}-[name]`,
      libraryTarget: 'umd',
      // jsonpFunction: `webpackJsonp_${name}`,
    },
  },
};

第六步,可能会报__webpack_public_path__错误,那就在.eslintrc.js里加入

globals: {
    __webpack_public_path__: true,
  },

子应用注册

第一步:创建主应用,并安装乾坤 npm i qiankun -S

vue create main
npm i qiankun -S

第二步:创建qiankun文件夹和index.js文件,结构如下:

image.png

import {
    registerMicroApps,
    runAfterFirstMounted,
    setDefaultMountApp,
    start,
  } from 'qiankun';
  
  /**
   * Step1 注册子应用
   */
  
  const microApps = [
    {
      name: 'sub-vue1',
      developer: 'vue3.x',
      entry: '//localhost:8080',
      activeRule: '',//这里最最最最最重要,这个需要匹配子应用的路由!!!!!
    },
  ];
  
  const apps = microApps.map((item) => {
    return {
      ...item,
      container: '#subapp-container', //  子应用挂载的 div
      props: {
        developer: item.developer,
        routerBase: item.activeRule,
      },
    };
  });
  
  // 子应用挂载的几个生命周期钩子
  registerMicroApps(apps, {
    beforeLoad: (app) => {
      console.log('before load app.name====>>>>>', app.name);
    },
    beforeMount: [
      (app) => {
        console.log('[LifeCycle] before mount %c%s', 'color: green;', app.name);
      },
    ],
    afterMount: [
      (app) => {
        console.log('[LifeCycle] after mount %c%s', 'color: green;', app.name);
      },
    ],
    afterUnmount: [
      (app) => {
        console.log('[LifeCycle] after unmount %c%s', 'color: green;', app.name);
      },
    ],
  });
  
  /**
   * Step2  设置挂载的子应用
   */
  setDefaultMountApp('/sub-vue');
  
  /**
   * Step3  启动应用
   */
  start();
  
  runAfterFirstMounted(() => {
    console.log('[MainApp] first app mounted');
  });
  
  export default apps;

第三步:修改主应用vue.config.js,也是有webpack5不兼容问题……

module.exports ={
  lintOnSave: false,//关闭eslint报错
  devServer: {
    port: '8443',
    // clientLogLevel: 'warning',
    // disableHostCheck: true,
    compress: true,
    historyApiFallback: true,
  },
}

第四步:修改一下主应用的APP.vue

//没有安装less的,安装一下less和less-loader
<template>
  <div class="layout-wrapper">
    <header class="layout-header">
      <div class="logo">MSP</div>
    </header>
    <main class="layout-main">
      <aside class="layout-aside">
        <ul>
          <li v-for="item in microApps" :key="item.name" @click="goto(item)">
            {{ item.name }}
          </li>
        </ul>
      </aside>
      <section class="layout-section" id="subapp-container"></section>
    </main>
  </div>
</template>

<script>
import microApps from './qiankun';

export default {
  name: 'App',
  data() {
    return {
      isLoading: true,
      microApps,
    };
  },
  methods: {
    goto(item) {
      history.pushState(null, item.activeRule, item.activeRule);
    },
  },
};
</script>

<style lang="less">
* {
  margin: 0;
  padding: 0;
}

html,
body,
.layout-wrapper {
  height: 100%;
  overflow: hidden;
}

.layout-wrapper {
  .layout-header {
    height: 50px;
    width: 100%;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
    line-height: 50px;
    position: relative;

    .logo {
      float: left;
      margin: 0 50px;
    }

    .userinfo {
      position: absolute;
      right: 100px;
      top: 0;
    }
  }

  .layout-main {
    height: calc(100% - 50px);
    overflow: hidden;
    display: flex;
    justify-content: space-evenly;

    .layout-aside {
      width: 190px;

      ul {
        margin: 50px 0 0 20px;
        border-right: 2px solid #aaa;

        li {
          list-style: none;
          display: inline-block;
          padding: 0 20px;
          color: #aaa;
          margin: 20px 0;
          font-size: 18px;
          font-weight: 400;
          cursor: pointer;

          &.active {
            color: #42b983;
            text-decoration: underline;
          }

          &:hover {
            color: #444;
          }
        }
      }
    }

    .layout-section {
      width: 100%;
      height: 100%;
    }
  }
}
</style>

最后成图: image.png