• [微前端实战]---041 框架初建(中央控制器, 子应用注册)


    框架初建(中央控制器, 子应用注册)


    回顾:

    1. 对子应用改造,然子应用在微前端环境启动起来,

    2. 入口做render,函数,暴露三个生命周期

    3. 配置vue.config.js/webpack.config.js +main.js/ index.js

    实现微前端框架基础功能,包括:应用注册、路由拦截、主应用生命周期添加、微前端生命周期添加、加载和解析html、加载和解析js、渲染、执行脚本文件等内容。

    修改各项目启动路径为9080,9081,9082,9083

    15.refact:修改各项目启动路径为908x

    一. 中央控制器

    主应用: 中央控制器

    主应用通过vue3构建

    $	npm install @vue/cli@4.5.0 -g
    
    • 1
    $	vue create main
    
    • 1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CPhWF4v9-1661697368731)(img/image-20220828193856000.png)]

    <template>
      <Header/>
      <MainNav />
      <div class="sub-container">
        <Loading v-show="loading"/>
        <div v-show="!loading" id="sub-container">子应用内容div>
      div>
      <Footer/>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    App.vue

    <template>
      <Header />
      <MainNav />
      <div class="sub-container">
        <Loading v-show="loading" />
        <div v-show="!loading" id="sub-body">子应用内容</div>
      </div>
      <Footer />
    </template>
    
    <script>
    import { ref } from 'vue'
    
    import Header from "./components/Header";
    import MainNav from "./components/MainNav";
    import Loading from "./components/Loading";
    import Footer from "./components/Footer";
    
    
    export default {
      name: 'App',
      components: {
        Header,
        MainNav,
        Loading,
        Footer
      },
      setup() {
        // 声明双向数据ref
        const loading = ref(true)
    
        setTimeout(()=>{// 3s 后关闭 loding
          loading.value = false
        },3000)
    
        return {
          loading,
        }
      }
    }
    </script>
    
    <style>
    html,
    body,
    #micro_web_main_app {
      width: 100%;
    height: 100%;
    }
    
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    .sub-container {
      min-height: 100%;
      position: relative;
    }
    
    #micro-container {
      min-height: 100%;
      width: 100%;
    }
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    通过一个v-show, loading变量, 控制显示隐藏

    components/MainNav.vue

    导航部分

    <template>
      <div class="main-nav-container">
        <div class="main-nav-content">
          <!-- logo内容 -->
          <div class="main-nav-logo">
            <img src="" alt="">
          </div>
    
          <!-- 导航列表详情 -->
          <div class="main-nav-list">
            <div v-for="(item, index) in NAV_LIST" :class="{ 'main-nav-active': currentIndex === index }" :key="index"
              @click="setCurrentIndex(item, index)">
              {{ item.name }}
            </div>
          </div>
    
          <!-- 搜索 -->
          <div class="main-nav-search">
            <div class="main-nav-search-icon">
              <img src="../assets/blue-search.png" alt="">
            </div>
            <div class="main-nav-search-input">
              <input type="text" id="main-nav-search" v-if="searchStatus" @blur="setSearchStatus(false)">
              <div class="main-nav-search-input-fake" v-else @click="setSearchStatus(true)">
                快速搜索
              </div>
            </div>
            <div class="main-nav-search-button">
              搜索
            </div>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import { ref, watch } from 'vue'
    export default {
      name: 'MainNav',
      setup() {
        const NAV_LIST = [
        {
          name: '首页',
          status: true,
          value: 0,
          url: '/vue3/index',
          hash: '',
        },
        {
          name: '资讯',
          status: false,
          value: 1,
          url: '/react15/information',
        },
        {
          name: '视频',
          status: false,
          value: 2,
          url: '/react15/video',
          hash: '',
        },
        {
          name: '选车',
          status: false,
          value: 3,
          url: '/vue3/select',
          hash: '',
        },
        {
          name: '新能源',
          status: false,
          value: 4,
          url: '/vue2/energy',
          hash: '',
        },
        {
          name: '新车',
          status: false,
          value: 5,
          url: '/react17/new-car',
          hash: '',
        },
        {
          name: '排行',
          status: false,
          value: 6,
          url: '/react17/rank',
          hash: '',
        },
      ]
    
        const currentIndex = ref(0) // 创建响应式变量
        const setCurrentIndex = (data, index) => {
          currentIndex.value = index
        }
    
        const searchStatus = ref(true)
        const setSearchStatus = (type) => {
          searchStatus.value = type
        }
        return {
          NAV_LIST,
          currentIndex,
          setCurrentIndex,
          searchStatus,
          setSearchStatus,
    
        }
      }
    }
    </script>
    <style lang="scss" scoped>
    ...
    </style>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115

    public/index.html

        
    • 1

    main.js

    import { createApp } from 'vue'
    import App from './App.vue'
    
    createApp(App).mount('#micro_web_main_app')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注入到这个micro_web_main_app节点

    16.中央控制器-主应用开发

    二. 子应用注册

    2.1. 抽离导航

    抽离导航–>src/const/nav.js

    export const NAV_LIST = [...]
    
    • 1

    components/MainNav.vue

    + import { NAV_LIST } from '../const/nav'
    
    • 1

    vue3使用路由进行跳转:

    • import {useRouter, useRoute} from ‘vue-router’

    • router.push(data.url)

    router/index.js

    import { createRouter, createWebHistory,createWebHashHistory } from 'vue-router';
    
    const routes = [
      {
        path: '/',
        component: () => import('../App.vue'),
      },
      {
        path: '/react15',
        component: () => import('../App.vue'),
      },
      {
        path: '/react16',
        component: () => import('../App.vue'),
      },
      {
        path: '/vue2',
        component: () => import('../App.vue'),
      },
      {
        path: '/vue3',
        component: () => import('../App.vue'),
      },
    ];
    
    const router =  (basename='')=>createRouter({
    //   history: createWebHashHistory(),
      history: createWebHistory(basename),
      routes,
    });
    
    export default router();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    main.js

    createApp(App).use(router).mount('#micro_web_main_app')
    
    • 1

    components/MainNav.vue

    <script>
    import { ref, watch } from 'vue'
    import { NAV_LIST } from '../const/nav'
    import {useRouter, useRoute} from 'vue-router'
    export default {
      name: 'MainNav',
      setup() {
        const router = useRouter()
        const route = useRoute() // 获取当前路由对象
    
        // 刷新时候,在当前路由
        watch(route,(val)=>{
          console.log(val);
          // console.log(val.fullPath) // 当前路由
          for (let i = 0; i < NAV_LIST.length; i++) {
            if (val.fullPath.indexOf(NAV_LIST[i].url)!==-1) { // 如果当前路由与路由匹配上
               currentIndex.value = i  // 设置active
            }
          }
        }, {deep: true})    // 深度监听
    
        const currentIndex = ref(0) // 创建响应式变量
        
        const setCurrentIndex = (data, index) => {
          // 优化:如果当前路由就是当前的路由,就不要触发set
          if (data.url === route.fullPath) {
            return ;
          }
    
          currentIndex.value = index
          router.push(data.url)
        }
    
        const searchStatus = ref(true)
        const setSearchStatus = (type) => {
          searchStatus.value = type
        }
        return {
          NAV_LIST,
          currentIndex,
          setCurrentIndex,
          searchStatus,
          setSearchStatus,
    
        }
      }
    }
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    1. 刷新时候,在当前路由
    2. 优化:如果当前路由就是当前的路由,就不要触发set
    2.2 创建store,激活规则

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LKKjgkki-1661697368735)(img/image-20220828223044842.png)]

    /store/sub.js

    // vue2
    // - http://:localhost:9080/#/
    //     - energy
    
    // vue3
    // - http://:localhost:9081/#/
    //     - index
    //     - select
    // react15
    // - http://:localhost:9082/#/
    //    -/information
    //    -/information-last
    //    -/video
    //    -/video-last
    // react17
    // - http://:localhost:9083/#/
    //     -/login
    //     -/new-car
    //     -/rank
    
    // ```
    
    // 子应用列表
    export const subNavList = [
        {
            name:'react15', //子应用名称
            activeRule:'/react15', // 激活规则
            container:'#micro-container' ,// 显示的容器,唯一标识
            entry:'//localhost:9082/' // 启动的入口
        },
        {
            name:'react17', 
            activeRule:'/react17', 
            container:'#micro-container',
            entry:'//localhost:9083/' // 启动的入口
    
        },
        {
            name:'vue2', 
            activeRule:'/vue2', 
            container:'#micro-container',
            entry:'//localhost:9080/'
        },
        {
            name:'vue3', 
            activeRule:'/vue3', 
            container:'#micro-container',
            entry:'//localhost:9081/'
        }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    /store/utils.js

    import { MicroStart } from '../../micro'
    
    const { registerMicroApps }= MicroStart
    // 注册子应用
    export const registerApp=(list)=>{
        // 注册到微前端框架
        registerMicroApps(list)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    main.js注册

    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    import { subNavList } from './store/sub'
    // 主应用引入 util 方法
    import { registerApp } from './store/utils'
    
    + registerApp(subNavList)
    
    createApp(App).use(router).mount('#micro_web_main_app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0oKF1Gbv-1661697368737)(img/image-20220828223022963.png)]

    micro/start.js

    // start 文件
    const registerMicroApps = (appList)=>{
        // 注册到window上
        window.appList = appList
    }
    
    
    export default {
        registerMicroApps
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    micro/index.js

    // 引入文件
    export {default as MicroStart } from './start'
    
    • 1
    • 2

    输入window.appList,将其注册到主应用

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x9BbhMiK-1661697368738)(img/image-20220828221553817.png)]

    一般不能将其放到全局,所以进行优化,后续通过getList方法获取整体内容

    新建const/subApps.js

    let list = []
    
    export const getList = () => list
    
    export const setList = (appList) => list = appList
    
    • 1
    • 2
    • 3
    • 4
    • 5

    优化: 将其保存在内部变量中, 通过getList方法获取整体内容

    micro/start.js

    import { setList } from './const/subApps'
    // start 文件
    const registerMicroApps = (appList)=>{
        // 注册到window上
        // window.appList = appList
       + setList(appList)
    }
    
    
    export default {
        registerMicroApps
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    17.中央控制器-注册子应用

    回顾:

    1. 通过useRouter(路由跳转方法, push,…), 与useRoute(路由信息)
    2. 子应用列表subList, (name, activeRule, container, entry)
    3. 注册到主应用registerApp

    这里可以选择其他的变量保存策略

  • 相关阅读:
    【JavaEE】Spring 事务传播机制
    浅谈软件性能提升相关的概念
    [NLP]—sparse neural network代表性工作简述
    前端面试常问的题目(持续更新中)
    如何培养单元测试的习惯?怎样才算一个好的单元测试?
    Go_原子操作和锁
    pytorch实战---IMDB情感分析
    『忘了再学』Shell基础 — 3、echo命令的介绍与使用
    线性表顺序存储结构--(Java)
    橘猫去水印小程序源码(可自定义解析接口、后端使用PHP)
  • 原文地址:https://blog.csdn.net/qq_35812380/article/details/126575681