vue+single-spa+ElementUi项目demo

本文介绍了一种微前端架构的实现方式,详细讲述了如何在Vue项目中引入ElementUI,并展示了登录页和主页面的设计。同时,文章还探讨了路由配置及组件的具体改造方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

效果图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  1. 接着上次的前端微服务继续深入改造

前面的demo: 微前端demo

  1. 项目中安装ElemenUi框架
npm i element-ui -S
  1. 在app1中引入ElementUi

官网做法:引入ElementUi

main.js改造:

import Vue from 'vue'
import App from '@/layout'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css';
import router from './router'

Vue.use(ElementUI);
new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

同理改造app2中的main.js: 主要关注如何引入ElementUi

import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui'
import router from './router'
import singleSpaVue from 'single-spa-vue'
Vue.config.productionTip = false
/**
 * 子应用main.js
 */
 Vue.use(ElementUI);
const appOptions = {
  el: '#microApp',
  router,
  render: h => h(App)
}
// if(window.singleSpaNavigate) {
//   __webpack_public_path__="http://localhost:8082/"
// }
// 支持应用独立运行、部署,不依赖于基座应用
if (!window.singleSpaNavigate) {
  delete appOptions.el
  new Vue(appOptions).$mount('#app')
}
// 基于基座应用,导出生命周期函数
const vueLifecycle = singleSpaVue({
  Vue,
  appOptions
})
export function bootstrap () {
  console.log('app2 bootstrap')
  return vueLifecycle.bootstrap(() => {})
}
export function mount () {
  console.log('app2 mount')
  return vueLifecycle.mount(() => {})
}
export function unmount () {
  console.log('app2 unmount')
  return vueLifecycle.unmount(() => {})
}

  1. 新建一个登陆页
    在src目录下新建layout目录并在下面新建login目录
    在这里插入图片描述
    在layout目录下新建index.vue:
<template>
  <div id="app" class="app">
    <!-- <router-view /> -->
    <keep-alive name="main" :include="'Operation'"><router-view /></keep-alive>
  </div>
</template>
<style>
#app {
  min-width: 1280px;
  height: 100%;
  background-color: #f0f2f5;
}
</style>

在login目录下新建index.vue:

<template>
  <div id="app" >
      <el-form ref="form" :model="form" label-width="80px">
        <el-form-item label="用户名">
          <el-input v-model="form.name"></el-input>
        </el-form-item>
        <el-form-item label="密码">
          <el-input v-model="form.pwd"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="onSubmit">登 录</el-button>
          <el-button>取消</el-button>
        </el-form-item>
      </el-form>
  </div>
</template>
<script>
export default{
  data() {
    return {
      form: {
        name: "",
        pwd: "",
      }
    };
  },
  methods: {
    onSubmit(){
      this.$router.push({path: '/operation'})
    }
  }
}
</script>
  1. 搞个主页面
    在src目录下新建operation目录并新建index.vue文件

/* eslint-disable */
<template>
  <!-- <div>
    <div id="nav">
      <router-link to="/home">app1</router-link> |
      <router-link to="/about">app1-about</router-link> |
      <router-link to="app2#/home">app2</router-link> |
      <router-link to="app2#/about">app2-about</router-link>
      <button @click="test">测试</button>
    </div>
    <router-view/>
    <div id="microApp">
    </div>
  </div> -->
<el-container style="height: 100%; border: 1px solid #eee">
  <el-header style="text-align: right; font-size: 12px">
    <el-dropdown>
      <i class="el-icon-setting" style="margin-right: 15px"></i>
      <el-dropdown-menu slot="dropdown">
        <el-dropdown-item>查看</el-dropdown-item>
        <el-dropdown-item>新增</el-dropdown-item>
        <el-dropdown-item>删除</el-dropdown-item>
      </el-dropdown-menu>
    </el-dropdown>
    <span>王小虎</span>
  </el-header>
  <el-container>

    <el-aside width="200px" style="background-color: #FFF;">
      <el-menu :default-openeds="['1']">
        <el-submenu index="1">
          <template slot="title"><i class="el-icon-message"></i>导航一</template>
          <el-menu-item-group>
            <el-menu-item @click="test('/app2#/home')" index="1-1">打开App2-Home</el-menu-item>
            <el-menu-item @click="test('/app2#/about')" index="1-2">打开App2-About</el-menu-item>
          </el-menu-item-group>
          <el-menu-item-group>
            <el-menu-item @click="test('/operation/home')" index="1-3">打开App1-Home</el-menu-item>
          </el-menu-item-group>
        </el-submenu>
      </el-menu>  
    </el-aside>

    <el-main>
      <router-view id="base" />
      <div id="microApp"></div>
    </el-main>
  </el-container>
</el-container>
</template>
<script>
import { single } from "@/single-spa-config";
export default {
  name: "Operation",
  methods: {
    test(uri){
      this.$router.push({path: uri});
    }
  },
  mounted(){
    single();
  }
}
</script>

<style lang="scss" scoped>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
 
#nav {
  padding: 30px;
}
 
#nav a {
  font-weight: bold;
  color: #2c3e50;
}
 
#nav a.router-link-exact-active {
  color: #42b983;
}

.el-header {
  background-color: #B3C0D1;
  color: #333;
  line-height: 60px;
}

.el-aside {
  color: #333;
}
#microApp {
  background-color: #fff;
}
#base {
  background-color: #fff;
}
/deep/ .el-main {
  background-color: #fff;
  padding: 20px !important;
  margin: 15px !important;
}
</style>

  1. app1的路由改造:
import VueRouter from 'vue-router'
import Vue from 'vue'
import Home from '@/views/home'
import About from '@/views/about';
// import Hello from '@/components/HelloWorld';
import APP from "@/operation";
// import MainPage from '@/components/main';
import login from '@/layout/login';
Vue.use(VueRouter)
const routes = [
    { path: '/home', component: Home },
    { path: '/about', component: About },
    { path: '*', component: APP },
    { path: '/operation', component: APP, children: [
        // {
        // path: '/',
        // redirect: '/home'
        // },
        { path: 'home', component: Home }
    ]},
    { path: '/operation/', component: login }
];
const router = new VueRouter({
    mode: 'history',
    // 通过环境变量来配置路由的 base url
    // base: process.env.VUE_APP_BASE_URL,
    routes
});
export default router

app2改造:

  1. views目录下的about.vue文件:

<!-- /views/About.vue 
<template>
  <div class="about">
    <h1>app2 about page</h1>
  </div>
</template>
-->
<template>
  <el-form ref="form" :model="form" label-width="80px">
    <el-form-item label="活动名称">
      <el-input v-model="form.name"></el-input>
    </el-form-item>
    <el-form-item label="活动区域">
      <el-select v-model="form.region" placeholder="请选择活动区域">
        <el-option label="区域一" value="shanghai"></el-option>
        <el-option label="区域二" value="beijing"></el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="活动时间">
      <el-col :span="11">
        <el-date-picker type="date" placeholder="选择日期" v-model="form.date1" style="width: 100%;"></el-date-picker>
      </el-col>
      <el-col class="line" :span="2">-</el-col>
      <el-col :span="11">
        <el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
      </el-col>
    </el-form-item>
    <el-form-item label="即时配送">
      <el-switch v-model="form.delivery"></el-switch>
    </el-form-item>
    <el-form-item label="活动性质">
      <el-checkbox-group v-model="form.type">
        <el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
        <el-checkbox label="地推活动" name="type"></el-checkbox>
        <el-checkbox label="线下主题活动" name="type"></el-checkbox>
        <el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
      </el-checkbox-group>
    </el-form-item>
    <el-form-item label="特殊资源">
      <el-radio-group v-model="form.resource">
        <el-radio label="线上品牌商赞助"></el-radio>
        <el-radio label="线下场地免费"></el-radio>
      </el-radio-group>
    </el-form-item>
    <el-form-item label="活动形式">
      <el-input type="textarea" v-model="form.desc"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">立即创建</el-button>
      <el-button>取消</el-button>
    </el-form-item>
  </el-form>  
</template>

<script>
  export default {
    data() {
      return {
        form: {
          name: '',
          region: '',
          date1: '',
          date2: '',
          delivery: false,
          type: [],
          resource: '',
          desc: ''
        }
      }
    },
    methods: {
      onSubmit() {
        console.log('submit!');
      }
    }
  }
</script>
  1. view目录下home.vue改造

<!-- /views/Home.vue 
<template>
  <div class="home">
    <h1>app2 home page</h1>
  </div>
</template>
-->

<template>
  <el-table
    :data="tableData"
    style="width: 100%"
    :row-class-name="tableRowClassName">
    <el-table-column
      prop="date"
      label="日期"
      width="180">
    </el-table-column>
    <el-table-column
      prop="name"
      label="姓名"
      width="180">
    </el-table-column>
    <el-table-column
      prop="address"
      label="地址">
    </el-table-column>
  </el-table>
</template>

<style>
  .el-table .warning-row {
    background: oldlace;
  }

  .el-table .success-row {
    background: #f0f9eb;
  }
</style>

<script>
  export default {
    methods: {
      // eslint-disable-next-line
      tableRowClassName({row, rowIndex}) {
        if (rowIndex === 1) {
          return 'warning-row';
        } else if (rowIndex === 3) {
          return 'success-row';
        }
        return '';
      }
    },
    data() {
      return {
        tableData: [{
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        }, {
          date: '2016-05-04',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        }, {
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        }, {
          date: '2016-05-03',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        }]
      }
    }
  }
</script>
 
  1. app2的路由不需要动以为我们只改动了组件,没有任何其他变动
整个页面展示说明:

主体页面构造在operation目录里面的组件。
在这里插入图片描述
整个主页面是显示在绑定在index.html的< router-view>中的
在这里插入图片描述
然后主页面operation/index.vue中又使用了一个< router-view>

要想保持这种显示布局就只有加的app1的组件路由都要写在/operation路由的子路由中,不然就会直接显示在绑定在index.html的< router-view>中了,也就是整个页面显示了,而不是我们定义的一块主显示区域。

在这里插入图片描述

遇到的问题:

app1中的子路由浏览器刷新直接空白页
在这里插入图片描述
app.js,chunk-vendors.js是啥啊,我们前面不是运行npm run build打包生成了dist目录吗,打开看看就大概明白了,
app.js: vue编译的项目代码
chunk-vendors.js :它是所有第三方模块的捆绑包
在这里插入图片描述

在这里插入图片描述查看app1主应用根目录下的vue.config.js文件在这里插入图片描述
改完需要重启app1主应用

再次刷新app1主应用下的子路由就没有出现资源加载不到的问题了

-----结束-----

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值