micro-app在vue-element-admin中一些使用研究

1、简述

本文承接上一篇micro-app在vue-element-admi中的搭建,对micro-app在vue-element-admin中的一些平时开发中常用的功能做了一些研究。本文代码

2、路由

关于路由,这边从两方面进行研究,一方面是对菜单的配置,另一方面是页面之间的跳转。下面分别介绍一下:

2-1、路由菜单配置

关于路由的配置,之前搭建vue-element-admin项目时,将子应用嵌入到基座时已经对路由的配置进行了搭建,子应用1为例具体如下:
micro-app在vue-element-admin中一些使用研究_第1张图片
如果是配置菜单的话,以上配置就可以了。配置代码如下:
micro-app-element\vue-element-base\src\router\modules\first-child.js

// 子应用1路由菜单
import Layout from '@/layout'
import { CHILD_PREFIX } from '@/micro/config'


const appFirstRouter = {
  path: `/${CHILD_PREFIX}/first-child`,
  component: Layout,
  redirect: `/${CHILD_PREFIX}/first-child`,
  name: 'FirstChild',
  meta: {
    title: '子应用模块',
    icon: 'nested'
  },
  children: [
    {
      path: 'menu1',
      name: 'Menu1',
      meta: { title: '子应用菜单1' }
    },
    {
      path: 'menu2',
      name: 'Menu2',
      meta: { title: '子应用菜单2' }
    }
  ]
}
export default appFirstRouter

micro-app-element\vue-element-first\src\router\modules\nested.js

/** When your routing table is too long, you can split it into small modules **/


import Layout from '@/layout'


console.log(' window.__MICRO_APP_BASE_ROUTE__', window.__MICRO_APP_BASE_ROUTE__)
const nestedRouter = {
  path: window.__MICRO_APP_BASE_ROUTE__ || '/nested',
  component: Layout,
  // redirect: '/nested/menu1/menu1-1',
  name: 'Nested',
  meta: {
    title: '子应用',
    icon: 'nested'
  },
  children: [
    {
      path: 'menu1',
      component: () => import('@/views/nested/menu1/index'), // Parent router-view
      name: 'Menu1',
      meta: { title: '子应用菜单11' }
    },
    {
      path: 'menu2',
      name: 'Menu2',
      component: () => import('@/views/nested/menu2/index'),
      meta: { title: '子应用菜单22' }
    }
  ]
}


export default nestedRouter

2-2、页面之间跳转

我们代码开发中,有很多场景都是一个菜单中有一个标签或按钮,点击可以直接跳转到另一个菜单。因为之前都是在同一个应用里,跳转肯定是没问题的。但是使用微前端后,可能会从基座菜单跳转到子应用菜单,也可能会从子应用菜单跳转到基座菜单,还有可能是子应用直接互相跳转,下面对这些跳转都做了尝试

2-2-1、子应用之间的互相跳转

举例:从子应用1的菜单1跳转到子应用2的菜单1,实现效果如下图所示:

对于应用之间的跳转,有如下两个地方要修改:
(1)基座:在一开始搭建路由的时候,在基座中调用了子应用,如果要实现应用之间互相跳转,基座部分需要获取子路由传递的信息,具体实现如下:
micro-app在vue-element-admin中一些使用研究_第2张图片
micro-app-element\vue-element-base\src\layout\components\AppMain.vue

<micro-app
  v-if="isChild"
  v-bind="micro"
  destory
  @datachange="handleDataChange"
/>
/**
* 获取子路由传递的信息
* */
handleDataChange(event) {
  const data = event.detail.data
  if (data.route) this.$router.push({ name: data.route.name })
},

(2)子应用点击部分的设置
micro-app在vue-element-admin中一些使用研究_第3张图片
micro-app-element\vue-element-first\src\views\nested\menu1\index.vue

<div style="height: 50px;">
  <el-button type="primary" @click="jumpApp2('DynamicTable')">我想从子应用1菜单1跳转到子应用2菜单1</el-button>
</div>
methods: {
  /**
   * 点击跳转到页面
   * @param name
   */
  jumpApp2(name) {
    // 向基项目发送数据
    window.microApp && window.microApp.dispatch({ route: { name }})
  }
}
2-2-2、子应用跳转到基座

举例:从子应用1的菜单2跳转到基座图标页,实现效果如下图所示:

有了2-2-1的基础后,接下来的操作就方便很多,不需要再去修改基座了,之间在子应用里面实现跳转即可
micro-app在vue-element-admin中一些使用研究_第4张图片
micro-app-element\vue-element-first\src\views\nested\menu2\index.vue

<template>
  <div style="padding:30px;">
    我是子应用菜单2
    <div style="height: 50px;">
      <el-button type="primary" @click="jumpAppBase('Icons')">我想从子应用1菜单2跳转到基座图标页</el-button>
    </div>
    <el-alert :closable="false" title="menu 2" />
  </div>
</template>
<script>
export default {
  name: 'Menu2',
  methods: {
    /**
       * 点击跳转到页面
       * @param name
       */
    jumpAppBase(name) {
      // 向基项目发送数据
      window.microApp && window.microApp.dispatch({ route: { name }})
    }
  }
}
</script>
2-2-3、基座跳转到子应用

举例:从基座引导页跳转到子应用1菜单2,实现效果如下图所示:

基座跳转到子应用与上面2-2-1和2-2-2方法不同,需要注意
首先从官网中可以看出,跳转的时候路由方式不一样,url也有所不用,如果是哈希需要加“#”,如果不知道自己的路由方式,可以在router/index.js下去找mode,默认是哈希。我这边就是哈希

micro-app在vue-element-admin中一些使用研究_第5张图片
接下来按照官网介绍进行配置即可
micro-app在vue-element-admin中一些使用研究_第6张图片
micro-app在vue-element-admin中一些使用研究_第7张图片
micro-app-element\vue-element-base\src\views\guide\index.vue

<template>
  <div class="app-container">
    <aside>
      {{ $t('guide.description') }}
      <a href="https://github.com/kamranahmedse/driver.js" target="_blank">driver.js.</a>
    </aside>
    <el-button icon="el-icon-question" type="primary" @click.prevent.stop="guide">
      {{ $t('guide.button') }}
    </el-button>
    <div style="height: 50px;">
      <el-button type="primary" @click="jumpApp1()">我想从基座跳转到子应用1菜单2</el-button>
    </div>
  </div>
</template>


<script>
import Driver from 'driver.js' // import driver.js
import 'driver.js/dist/driver.min.css' // import driver.js css
import steps from './steps'
import { CHILD_PREFIX } from '../../micro/config'


export default {
  name: 'Guide',
  data() {
    return {
      driver: null
    }
  },
  mounted() {
    this.driver = new Driver()
  },
  methods: {
    guide() {
      this.driver.defineSteps(steps)
      this.driver.start()
    },
    /**
     * 基座跳转到子应用
     */
    jumpApp1() {
      window.history.pushState(null, '', `/#/${CHILD_PREFIX}/first-child/menu2`)
      // 主动触发一次popstate事件
      window.dispatchEvent(new PopStateEvent('popstate', { state: null }))
    }
  }
}
</script>

3、数据通信

关于这个数据通信,官网里讲了如下四点,感觉看着蛮不舒服的。其实按我们正常的思维,传值与取值是一起使用的
(1)子应用获取来自基座应用的数据
(2)子应用向基座应用发送数据
(3)基座应用向子应用发送数据
(4)基座应用获取来自子应用的数据
所以将以上(1)(3)和(2)(4)合并起来作为两点进行研究

3-1、基座发送数据,子应用获取数据

基座向子应用传值有两种方式:

3-1-1、data属性发送数据

micro-app在vue-element-admin中一些使用研究_第8张图片
基座发送数据:

<micro-app
  v-if="isChild"
  v-bind="micro"
  destory
  :data="dataForChild"
  @datachange="handleDataChange"
/>

dataForChild: { type: 'data属性发送数据给子应用' },

子应用获取数据:

created() {
  const data = window.microApp.getData() // 返回基座下发的data数据
  console.log('子应用获取父应用数据', data)
},
3-1-2、基座手动发送数据

micro-app在vue-element-admin中一些使用研究_第9张图片
基座

import microApp from '@micro-zoe/micro-app'
microApp.setData('first-child', { type: '基座手动发送新的数据' })

子应用

<template>
  <div style="padding:30px;">
    我是子应用菜单2
    <div style="height: 50px;">
      <el-button type="primary" @click="jumpAppBase('Icons')">我想从子应用1菜单2跳转到基座图标页</el-button>
    </div>
    <el-alert :closable="false" title="menu 2" />
  </div>
</template>
<script>
export default {
  name: 'Menu2',
  created() {
    // const data = window.microApp.getData() // 返回基座下发的data数据
    // console.log('子应用获取父应用数据', data)
    /** 绑定数据【data属性】监听事件 */
    window.microApp && window.microApp.addDataListener(this.dataListener, true)
  },
  destroyed() {
    /** 移除数据【data属性】监听事件 */
    window.microApp && window.microApp.removeDataListener(this.dataListener)
  },
  methods: {
    dataListener(data) {
      console.log('来自基座应用的数据', data)
    },
    /**
       * 点击跳转到页面
       * @param name
       */
    jumpAppBase(name) {
      // 向基项目发送数据
      window.microApp && window.microApp.dispatch({ route: { name }})
    }
  }
}
</script>

3-2、子应用发送数据,基座获取数据

关于子应用发送数据,基座获取数据的,我们在前面写跳转的时候就遇到了
micro-app在vue-element-admin中一些使用研究_第10张图片
子应用

// 向基项目发送数据
  window.microApp && window.microApp.dispatch({ route: { name }})

基座

<micro-app
  v-if="isChild"
  v-bind="micro"
  destory
  :data="dataForChild"
  @datachange="handleDataChange"
/>
/**
* 获取子路由传递的信息
* */
handleDataChange(event) {
  const data = event.detail.data
  if (data.route) this.$router.push({ name: data.route.name })
},

4、隔离

4-1、样式隔离

micro-app有默认的样式隔离,我简单试了一下
(1)修改子应用的颜色,子应用发生变化,但是不会影响到基座的样式
micro-app在vue-element-admin中一些使用研究_第11张图片
(2)修改基座颜色,基座会发生变化,不会影响到子应用
micro-app在vue-element-admin中一些使用研究_第12张图片

4-2、元素隔离

micro-app也有默认的元素隔离,元素不会逃离元素边界,子应用只能对自身的元素进行增、删、改、查的操作。

5、资源共享

官网描述:当多个子应用拥有相同的js或css资源时,可以指定这些资源在多个子应用之间共享,在子应用加载时直接从缓存中提取数据,从而提高渲染效率和性能。我大概可以理解为在基座中配置资源共享,这样子应用就可以直接用这个资源了。那我好奇要是子应用单独运行呢?这个资源还存在吗?或者是就直接没有这些共享的资源了?
因此自己亲自试了一下,将子应用1引入的样式注释掉,在基座中引入,基座是没看出来有什么问题,但是子应用1因为失去了样式就变的乱七八糟,关于这一点网上也没有找到太多的内容

micro-app在vue-element-admin中一些使用研究_第13张图片
micro-app在vue-element-admin中一些使用研究_第14张图片
但是在下面6、组件共享实现后,可以用同一方式实现样式共享,具体可看6中介绍。

6、组件共享

在目前微前端搭建的基础上,可以发现一些问题,公共组件。如果一个组件在基座和子应用中都需要用到,目前的状态是每个项目都写一遍,这样很麻烦。所以要想个办法实现组件共享
关于共享,我这边看到一个 monorepo(单一代码库) ,差不多意思是单个代码库里包含了许多项目的代码,但是后面没用该方法,所以也不知道好不好实现。
我这边用的是后台大佬分享的这篇文章中的方法三,大体参考,但是实际还需要修改一番,接下来看看我的实现步骤:
注:我这边把通用组件都放在基座base中,如果你想单独建一个项目来放通用组件也行,具体看个人想法。

6-1、项目目录结构

如下图所示目录结构。基座和子应用都放在一个大的文件夹micro-app-element下,假装base中的组件是通用组件,我现在在子应用1vue-element-first中进行一些操作,来实现组件的共享
micro-app在vue-element-admin中一些使用研究_第15张图片

6-2、修改vue.config.js

参考文章中是修改webpack.js配置。我们项目是vue-element-admin。webpack的相关配置我这边找到是在vue.config.js中配置的,所以路径相关在vue.config.js中配置即可。
micro-app在vue-element-admin中一些使用研究_第16张图片

// 注:根据自己的项目结果及项目名称修改

console.log('__dirname', __dirname, typeof __dirname, path.join(path.parse(__dirname).dir, 'vue-element-base/src'), '\r\n', path.parse(__dirname))
// 注:只需要添加baseComponent那一行即可,如果想调用子应用2,可以在或其它可以在重新配置一条

resolve: {
  alias: {
    '@': resolve('src'),
    'baseComponent': path.join(path.parse(__dirname).dir, 'vue-element-base/src')
  }
}

6-3、配置路由共享组件

这边在子应用1的路由中随便改一下首页的路径,让子应用1去访问基座中的首页页面
micro-app在vue-element-admin中一些使用研究_第17张图片

{
  path: '/',
  component: Layout,
  redirect: '/dashboard',
  children: [
    {
      path: 'dashboard',
      // component: () => import('@/views/dashboard/index'),
      component: () => import('baseComponent/views/dashboard/index'),
      name: 'Dashboard',
      meta: { title: 'dashboard', icon: 'dashboard', affix: true }
    }
  ]
},

然后因为三个应用内容都差不多,去基座改一下首页
micro-app在vue-element-admin中一些使用研究_第18张图片
接下来看效果:
micro-app在vue-element-admin中一些使用研究_第19张图片

6-4、import导入共享组件

在6-3中尝试了在路由中直接修改路径共享到基座菜单的方法,接下来在尝试一下在页面中通过import导入基座组件的方法吧。同样在基座中随便找了个组件Dropzone,照着抄抄就好了
micro-app在vue-element-admin中一些使用研究_第20张图片
micro-app-element\vue-element-first\src\views\nested\menu1\index.vue

<template>
  <div style="padding:30px;">
    <div style="height: 50px;">
      <el-button type="primary" @click="jumpApp2('DynamicTable')">我想从子应用1菜单1跳转到子应用2菜单1</el-button>
    </div>
    <el-alert :closable="false" title="menu 1">
      我是子应用菜单1
      <div class="editor-container">
        <dropzone id="myVueDropzone" url="https://httpbin.org/post" @dropzone-removedFile="dropzoneR" @dropzone-success="dropzoneS" />
      </div>
      <router-view />
    </el-alert>
  </div>
</template>
<script>
import Dropzone from 'baseComponent/components/Dropzone'
export default {
  name: 'Menu1',
  components: { Dropzone },
  methods: {
    dropzoneS(file) {
      console.log(file)
      this.$message({ message: 'Upload success', type: 'success' })
    },
    dropzoneR(file) {
      console.log(file)
      this.$message({ message: 'Delete success', type: 'success' })
    },
    /**
     * 点击跳转到页面
     * @param name
     */
    jumpApp2(name) {
      // 向基项目发送数据d
      window.microApp && window.microApp.dispatch({ route: { name }})
    }
  }
}
</script>

然后同样为了明显的看清楚我这边子应用1嵌入了base组件,我同样在代码里加了一点描述用来区分

<div style="color: #ff4949;font-size: 18px;">我是基座的公共组件</div>

micro-app在vue-element-admin中一些使用研究_第21张图片
实现效果如下图所示:
micro-app在vue-element-admin中一些使用研究_第22张图片

7、总结

到这里,对micro-app在vue-element-admin中的使用就研究的差不多了,因为初学,可能也存在一些问题,所以欢迎搭建评论区留言纠正。

你可能感兴趣的:(微前端micro-app,micro-app,element-admin,微前端,组件共享,路由跳转)