likes
comments
collection
share

领导:我有个需求,你把我们项目的技术栈升级一下(终)

作者站长头像
站长
· 阅读数 8

流言四起

某位帅哥被领导叫进办公室并进行某种交易的事情曝光了,一时间办公室流传着各种版本,什么帅哥要给领导生孩子啊,什么领导一怒为红颜之类的声音一直存在😀。

作为当事人,为了避免这种离谱的流言继续流传,我只能出来解释了。

“咳咳,大家听好了,不是领导要给我生孩子,也不是领导因为我帅喜欢我,是领导叫我帮系统搞技术升级,用的是qiankun框架,之前聊到主应用模板,准备聊的是子应用模板

说完,众人一副《你说的话我一句都不信》的表情。

领导:我有个需求,你把我们项目的技术栈升级一下(终)

我只好继续解释

“不是,你们什么眼神,真的是技术升级,不是什么奇怪的交易”。面对众人的眼神,我继续狡辩。

为了防止事情进一步恶化,我只能掏出证据了,来看代码吧(里面用到的UI库就不去除了)

先修改一下vue.config.js文件,让子应用的构建可以适配qiankun

const { defineConfig } = require('@vue/cli-service')
const packageName = require('./package.json').name
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack: {
    output: {
      library: `${packageName}-[name]`,
      libraryTarget: 'umd',
      chunkLoadingGlobal: `webpackJsonp_${packageName}`
    },
  },
  devServer: {
    // qiankun
    headers: {
      'Access-Control-Allow-Origin': '*'
    }
  }
})

主要修改构建的输出文件,根据qiankun官网进行修改.

再看main.js


import './public-path'
import { createApp, App as typeApp } from 'vue'
import App from '@/App.vue'
import { createRouter, createWebHistory } from 'vue-router'
import { MicroAppStateActions } from 'qiankun'
import routes from '@/router'
import store from '@/store'
import permission from './permission'
import action from '@/directives/action'
import { VueAxios } from '@/api/request'
import ArcoVue from '@arco-design/web-vue'
import '@arco-design/web-vue/dist/arco.css'

interface LifecycleProps extends MicroAppStateActions {
  container: Element
}

let router = null
let mountApp = null
let ROUTER_BASE = ''
export let app: typeApp

function render (props?: LifecycleProps): void {
  mountApp = '#app'
  if (props) {
    mountApp = props.container.querySelector('#app') || ''
  }
  app = createApp(App)
  router = createRouter({
    history: createWebHistory(ROUTER_BASE),
    routes
  })
  
  // 注册权限 store 路由
  app.use(store)
    .use(permission, {
      router
    })
    .use(router).use(VueAxios).use(ArcoVue).use(action).mount(mountApp)
}

if (!window.__POWERED_BY_QIANKUN__) {
  render()
}

// 注册qiankun全局状态
function qiankunStore (props: LifecycleProps) {
  props.onGlobalStateChange && props.onGlobalStateChange(value => {
    ROUTER_BASE = value.MAIN_ROUTER_BASE || ''
    if (value.token) {
      // 如果主应用有token 则设置token
      store.commit('SET_TOKEN', {
        value: value.token,
        noSave: false
      })
    }
  }, true)
  // 注册修改全局状态的方法
  store.commit('QIANKUN_SET_GLOBAL', props.setGlobalState)
}

export async function bootstrap () {
  console.log('[vue] vue app bootstraped')
}

export async function mount (props: LifecycleProps) {
  console.log('[subapp] props from main framework', props)
  qiankunStore(props)
  await render(props)
}

export async function unmount () {
  app.unmount()
}

上面的代码是整个子应用中使用qiankun的主要代码,主要使用qiankun提供的几个API做一些事件的注册。

接下来是几个模板,直接上代码了。

App.vue

<template>
  <a-config-provider :locale="local">
    <router-view></router-view>
  </a-config-provider>
</template>

<script lang="ts">
import zhCn from '@arco-design/web-vue/es/locale/lang/zh-cn'

export default {
  name: 'App',
  data () {
    return {
      local: zhCn
    }
  }
}
</script>

<style lang="less">
// 微前端容器高度
#SubappViewportWrapper {
  height: 100%;
  #SubappViewport {
    height: 100%;
    > div {
      height: 100%;
    }
  }
}
.hide-micro-container {
  #SubappViewportWrapper {
    display: none;
  }
}
</style>

这里设置了微前端容器的高度

BasicLayout.vue

<template>
  <a-layout class="container">
    <a-layout-sider collapsible breakpoint="xl">
      <div class="logo">
        <img alt="Vue logo" src="../assets/logo.png">
      </div>
      <a-menu
        v-model:selected-keys="selectKeys"
        v-model:openKeys="openKeys"
        @menu-item-click="handleClickMenu"
      >
         <menu-item v-for="menu in menus" :key="menu.path" :menu="menu"></menu-item>
        </a-menu>
    </a-layout-sider>
    <a-layout>
      <a-layout-header>
        <div></div>
      </a-layout-header>
      <a-layout-content class="content">
        <div id="SubappViewportWrapper">
          <div id="SubappViewport">
            <div>
              <!-- 模拟主应用中的三层结构 -->
              <RouteView></RouteView>
            </div>
          </div>
        </div>
      </a-layout-content>
    </a-layout>
  </a-layout>
</template>
<script lang="ts" setup>
import { ref, watch, onMounted, computed, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
import store from '@/store'
import MenuItem from './MenuItem.vue'
import RouteView from './RouteView.vue'

const router = useRouter()
const menus = router.options.routes[0].children || []

const handleClickMenu = (key: string) => {
  router.push({
    name: key
  })
}


</script>

<style lang="less" scoped>
.container {
  height: 100vh;
}

.arco-layout-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 72px;
  background-color: #435279;
}
.logo {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 72px;
}
</style>

里面使用到的Route.vue和主应用中用到的是一样的,代码就不贴出来了,可以到上一篇去找。

大家终于相信我了

在我贴出了我的代码证据之后,众人才愿意相信我进去小黑屋是和领导讨论技术升级的方案。

还有就是解释一下为什么这么久才更新子应用模板,那是因为搞完了架构,要开始搞写业务了,忙忙忙。这才是技术升级最烦的地方---业务开发

还有就是在上一篇文章中,很多掘友说能一个iframe能搞定的事情,非要整这么复杂,根本没必要。

其实个人觉得,做项目的基础架构的时候,不能为了只考虑方便和现在,要考虑到之后的扩展,我觉得每个技术存在并且能被大家接受,还是有一定的意义的,但是所有的技术都是为了业务而存在,所以大家在考虑技术架构的时候,必要的还是以业务优先,不要为了用而用。(一点个人见解,勿喷)

最后,小杜祝大家新年快乐,事业步步高升,人人都玩帕鲁,可是你们不要成为帕鲁。

领导:我有个需求,你把我们项目的技术栈升级一下(终)

转载自:https://juejin.cn/post/7330178014133583882
评论
请登录