精华内容
下载资源
问答
  • 使用vue搭建页面多系统应用
    万次阅读
    2019-02-26 15:29:11

    一、多页面多系统应用

    1. 思路
      使用Vue搭建多页应用。所有系统都在同一目录下。配置多入口多出口。每个系统之间可以链接。每个系统内依然采用Vue单页应用开发。
    2. 组件复用性
      可以将所有的系统公共组件放到系统目录最外面,以达到组件复用。在系统内部依然将自己独立的组件封装,复用。这样可以最大限度的提高组件的复用性。
    3. 路由
      每个系统单独进行路由配置
    4. 数据管理
      每个系统数据仓库单独处理
    5. 目录结构
      在这里插入图片描述
    6. 效果
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在做Vue项目的时候,需要用对多个类似系统做一个集成。想过很多种方法,比如:完全单页应用,分开独立应用,最终还是测试了一下多页面开发多系统。

    准备工作:

    使用vue-cli搭建最基本的vue项目。

    修改webpack配置:

    在这一步里我们需要改动的文件都在build文件下,分别是:

    • utils.js
    • webpack.base.conf.js
    • webpack.dev.conf.js
    • webpack.prod.conf.js
      我就按照顺序放出完整的文件内容,然后在做修改或添加的位置用注释符标注出来
    utils.js

    最最后添加如下代码:

    
    /* 这里是添加的部分 ---------------------------- 开始 */
    
    // glob是webpack安装时依赖的一个第三方模块,还模块允许你使用 *等符号, 例如lib/*.js就是获取lib文件夹下的所有js后缀名的文件
    var glob = require('glob')
        // 页面模板
    var HtmlWebpackPlugin = require('html-webpack-plugin')
        // 取得相应的页面路径,因为之前的配置,所以是src文件夹下的pages文件夹
    var PAGE_PATH = path.resolve(__dirname, '../src/system')
        // 用于做相应的merge处理
    var merge = require('webpack-merge')
    
    
    //多入口配置
    // 通过glob模块读取pages文件夹下的所有对应文件夹下的js后缀文件,如果该文件存在
    // 那么就作为入口处理
    exports.entries = function() {
        var entryFiles = glob.sync(PAGE_PATH + '/*/*.js')
        var map = {}
        entryFiles.forEach((filePath) => {
            var filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
            map[filename] = filePath
        })
        return map
    }
    
    //多页面输出配置
    // 与上面的多页面入口配置相同,读取pages文件夹下的对应的html后缀文件,然后放入数组中
    exports.htmlPlugin = function() {
            let entryHtml = glob.sync(PAGE_PATH + '/*/*.html')
            let arr = []
            entryHtml.forEach((filePath) => {
                let filename = filePath.substring(filePath.lastIndexOf('\/') + 1, filePath.lastIndexOf('.'))
                let conf = {
                    // 模板来源
                    template: filePath,
                    // 文件名称
                    filename: filename + '.html',
                    // 页面模板需要加对应的js脚本,如果不加这行则每个页面都会引入所有的js脚本
                    chunks: ['manifest', 'vendor', filename],
                    inject: true
                }
                if (process.env.NODE_ENV === 'production') {
                    conf = merge(conf, {
                        minify: {
                            removeComments: true,
                            collapseWhitespace: true,
                            removeAttributeQuotes: true
                        },
                        chunksSortMode: 'dependency'
                    })
                }
                arr.push(new HtmlWebpackPlugin(conf))
            })
            return arr
        }
        /* 这里是添加的部分 ---------------------------- 结束 */
    
    webpack.base.conf.js
    module.exports = {
        context: path.resolve(__dirname, '../'),
        /* 修改部分 ---------------- 开始 */
        entry: utils.entries(),
        /* 修改部分 ---------------- 结束 */
        output: {
            path: config.build.assetsRoot,
            filename: '[name].js',
            publicPath: process.env.NODE_ENV === 'production' ?
                config.build.assetsPublicPath : config.dev.assetsPublicPath
        }
        ...
     }
    
    webpack.dev.conf.js
    plugins: [
            new webpack.DefinePlugin({
                'process.env': require('../config/dev.env')
            }),
            new webpack.HotModuleReplacementPlugin(),
            new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
            new webpack.NoEmitOnErrorsPlugin(),
            // https://github.com/ampedandwired/html-webpack-plugin
            /* 注释这个区域的文件 ------------- 开始 */
            // new HtmlWebpackPlugin({
            //   filename: 'index.html',
            //   template: 'index.html',
            //   inject: true
            // }),
            /* 注释这个区域的文件 ------------- 结束 */
            // copy custom static assets
            new CopyWebpackPlugin([{
                from: path.resolve(__dirname, '../static'),
                to: config.dev.assetsSubDirectory,
                ignore: ['.*']
            }])
    
            /* 添加 .concat(utils.htmlPlugin()) ------------------ */
        ].concat(utils.htmlPlugin())
    
    webpack.prod.conf.js
    /* 注释这个区域的内容 ---------------------- 开始 */
      // new HtmlWebpackPlugin({
      //   filename: config.build.index,
      //   template: 'index.html',
      //   inject: true,
      //   minify: {
      //     removeComments: true,
      //     collapseWhitespace: true,
      //     removeAttributeQuotes: true
      //     // more options:
      //     // https://github.com/kangax/html-minifier#options-quick-reference
      //   },
      //   // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      //   chunksSortMode: 'dependency'
      // }),
     /* 注释这个区域的内容 ---------------------- 结束 */
    

    添加:
    在这里插入图片描述

    目录结构介绍

    • src就是我所使用的工程文件了,assets,components,system分别是静态资源文件、组件文件、页面文件。

    • 前两个就不多说,主要是页面文件里,我目前是按照项目的模块分的文件夹,你也可以按照你自己的需求调整。然后在每个模块里又有三个内容:vue文件,js文件和html文件。这三个文件的作用就相当于做spa单页面应用时,根目录的index.html页面模板,src文件下的main.js和app.vue的功能。

    • 原先,入口文件只有一个main.js,但现在由于是多页面,因此入口页面多了,我目前就是两个:index和system2,之后如果打包,就会在dist文件下生成两个HTML文件:index.html和system2.html(可以参考一下单页面应用时,打包只会生成一个index.html,区别在这里)。

    注意的地方

    配置js时候:

    import Vue from 'Vue'
    import cell from './cell.vue'
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      render: h => h(cell)
    })
    

    页面跳转:

    可以写成:<a href='system2.html'></a>
    

    打包后的资源路径

    ├── dist
    │   ├── js
    │   ├── css
    │   ├── index.html
    │   └── system2.html
    
    更多相关内容
  • 本文以vue-cli3+为例,实现多系统集成下的分模块打包。

    本文以vue-cli3+为例,实现多系统集成下的分模块打包。分模块打包方式多种多样,下文可适用于多系统之间互不干扰,主系统可集成各子系统,各子系统又可单独运行的业务场景。

    一、目标

    我们要实现什么?所谓分模块打包,那么各个模块内就必须得有自己独立的入口文件,路由文件。按照这种构想,我在一个新的脚手架src目录下新建了一个projects目录:
    图1
    如上图,可以看到Aproject、B、C、D四个项目。我在A项目中建了assets,common和views文件夹,其中assets可以再建img和css的文件夹,common内可以放公共组件或者方法,views页面可以放页面,甚至你还可以建一个components文件夹专门用来放组件。

    好了,我们的视图目录结构大概就是上面的样子。我们期待的是,我们可以打包这个A模块这个‘小vue’,就像打包一个完整vue的项目一样。那么如何实现这部分呢?


    二、打包单个模块

    我们知道,在package.json中,有项目启动,打包的命令。
    在这里插入图片描述

    我们可以从这里入手。

    这里就不得不提到cross-env这个模块了。
    我们之前在设置生产环境,测试环境,开发环境时也会用到这个模块。在这里不详细表述了。

    cross-env:npm install --save-dev cross-env
    

    现在我们的思路大概是这样的,当我们执行打包命令的时候,通过cross-env去找到我们的入口文件,然后再打包。

    所以我们可以模仿环境变量的写法,在package中写入如下图代码。
    在这里插入图片描述
    代码:

        "dev:projectA": "cross-env PROJECT_NAME=projectA vue-cli-service serve",
        "dev:projectB": "cross-env PROJECT_NAME=projectB vue-cli-service serve",
        "dev:projectC": "cross-env PROJECT_NAME=projectC vue-cli-service serve",
        "dev:projectD": "cross-env PROJECT_NAME=projectD vue-cli-service serve",
        "build:projectA": "cross-env PROJECT_NAME=projectA vue-cli-service build",
        "build:projectB": "cross-env PROJECT_NAME=projectB vue-cli-service build",
        "build:projectC": "cross-env PROJECT_NAME=projectC vue-cli-service build",
        "build:projectD": "cross-env PROJECT_NAME=projectD vue-cli-service build",
    

    写完了这些,我们就可以着手模仿vue配置小vue的文件了。

    • 在main.js中配置如下代码:
            import Vue from "vue";
    		import App from "./App.vue";
    		import router from "./router";
    		import store from "./store";
    		
    		Vue.config.productionTip = false;
    		
    		new Vue({
    		    router,
    		    store,
    		    render: h => h(App)
    		}).$mount("#app");
    
    • 在App.vue中配置如下代码:
            <template>
    		  <div id="app">
    		    <router-view />
    		  </div>
    		</template>
    		
    		<style lang="less">
    		
    		</style>
    
    • 在router.js中配置如下代码
    		import Vue from "vue";
    		import Router from "vue-router";
    		import Home from "./views/Home.vue";
    		
    		Vue.use(Router);
    		
    		export default new Router({
    		  routes: [
    		    {
    		      path: "/",
    		      name: "home",
    		      component: Home
    		    }
    		  ]
    		});
    
    • 在page文件夹中建立Home.vue,写入如下代码:
    		<template>
    		  <div>
    		    我是a项目
    		  </div>
    		</template>
    		
    		<script>
    		export default {};
    		</script>
    		
    		<style></style>
    
    • 在项目最外层建立config文件夹,在其中新建projectsConfig.js写入:
    const config = {
      projectA: {
        pages: {
          index: {
            entry: "src/projects/projectA/main.js",
            template: "public/index.html",
            filename: "index.html"
          }
        },
        devServer: {
          port: 8080, // 端口地址
          open: false, // 是否自动打开浏览器页面
          host: "0.0.0.0", // 指定使用一个 host,默认是 localhost
          https: false, // 使用https提供服务
          disableHostCheck: true,
          // 设置代理
          proxy: {
            "/eopenhapi": {
              target: "http://open.jdpay.com",
              changeOrigin: true
            },
            "/hapi": {
              target: "http://open.jdpay.com",
              changeOrigin: true
            }
          }
        }
      },
      projectB: {},
      projectC: {}
    };
    module.exports = config;
    
    • 把projectsConfig.js并入vue.config.js,vue.config.js中代码如下
    const config = require("./config/projectsConfig.js");
    let projectName = process.env.PROJECT_NAME;
    
    module.exports = {
      ...config[projectName],
      // pages: conf.pages,
    
      // 基本路径
      // baseUrl: './',//vue-cli3.3以下版本使用
      publicPath: "./", // vue-cli3.3+新版本使用
    
      // 输出文件目录
      outputDir: "dist/" + projectName + "/"
    };
    

    写到这里我们就建立一个完整的小vue了。

    • 运行命令 cnpm run dev:projectA
      在这里插入图片描述

    • 运行命令 cnpm run build:projectA
      在这里插入图片描述
      效果完美。

    三、打包总项目及子系统

    一个大型项目必然会有公共模块,这里会写一个导航栏作为公共组件。

    1. 在projects下建立公共模块的文件夹common,写入前面A项目的目录结构,如图:
      在这里插入图片描述
    2. 在package.json中写入运行命令和打包命令。
     "dev:common": "cross-env PROJECT_NAME=common vue-cli-service serve",
     "build:common": "cross-env PROJECT_NAME=common vue-cli-service build",
    
    1. 在Home.vue中写公共导航

      这里会使用iview作为ui组件,但也因此有一个问题,我的A,B,C,D四个项目每个项目引入一遍UI框架,那打包出来整个项目将会非常的大,所以我们在项目必须采用按需引入的方式。(项目中还是下载整个ivew)

    写入如下代码:

    <template>
      <div class="main-content">
        <Layout>
          <header class="head-box">
            <Menu
              mode="horizontal"
              theme="primary"
              active-name="1"
              @on-select="menuClick"
            >
              <div class="layout-logo">Oralinge</div>
              <div class="layout-nav">
                <div class="layout-nav-content">
                  <!-- 系统列表 -->
                  <span v-for="(item, index) in systemList" :key="index">
                    <MenuItem
                      :name="item.basepath + '?systemId=' + item.systemId"
                      @click="go(item)"
                    >
                      <Icon type="ios-navigate"></Icon>
                      {{ item.title }}
                    </MenuItem>
                  </span>
                </div>
              </div>
              <div class="layout-right">
                <Dropdown>
                  <!-- 登录姓名 -->
                  <a href="javascript:void(0)">
                    {{ user.userName }}
                    <Icon type="ios-arrow-down"></Icon>
                  </a>
                  <!-- 退出登录 -->
                  <DropdownMenu slot="list">
                    <DropdownItem name="logout">退出登录</DropdownItem>
                  </DropdownMenu>
                </Dropdown>
              </div>
            </Menu>
          </header>
        </Layout>
        <iframe
          :src="systemUrl"
          width="100%"
          height="100%"
          frameborder="0"
          class="iframe"
          id="bossIframe"
        ></iframe>
      </div>
    </template>
    <script>
    import {
      Layout,
      Menu,
      MenuItem,
      Dropdown,
      DropdownItem,
      DropdownMenu
    } from "view-design";
    
    export default {
      components: {
        Layout,
        Menu,
        MenuItem,
        Dropdown,
        DropdownItem,
        DropdownMenu
      },
      data() {
        return {
          systemUrl: "",
          isFullscreen: false,
          loading: false,
          systemList: [
            {
              title: "A项目",
              basepath: "http://localhost:8080/#/",
              systemId: "A"
            },
            {
              title: "B项目",
              basepath: "http://localhost:8082/#/",
              systemId: "B"
            },
            {
              title: "C项目",
              basepath: "http://localhost:8083/#/",
              systemId: "c"
            },
            {
              title: "D项目",
              basepath: "http://localhost:8084/#/",
              systemId: "D"
            }
          ],
          user: {}
        };
      },
      mounted() {
        this.systemUrl =
          this.systemList[0].basepath + "?systemId=" + this.systemList[0].systemId;
      },
      methods: {
        menuClick(name) {
          this.systemUrl = name;
        }
      }
    };
    </script>
    
    <style lang="less" scoped>
    @head-height: 50px;
    .main-content {
      height: 100%;
      padding-top: @head-height;
      box-sizing: border-box;
      overflow: hidden;
    }
    .head-box {
      width: 100%;
      height: @head-height;
      line-height: @head-height;
      position: fixed;
      top: 0;
      left: 0;
      min-width: 1200px;
    
      .ivu-menu-horizontal {
        height: 100%;
        line-height: @head-height;
      }
      .layout-logo {
        display: inline-block;
        width: 200px;
        color: #fff;
        font-size: 28px;
        text-align: center;
        vertical-align: top;
        position: absolute;
        left: 0;
        top: 0;
        background-color: #2d8cf0;
        z-index: 5;
      }
      .layout-nav {
        display: inline-block;
        width: 100%;
        height: 100%;
        padding-left: 200px;
        padding-right: 100px;
        box-sizing: border-box;
        overflow-x: auto;
        z-index: 4;
        &-content {
          //   width: 100%;
          overflow: hidden;
          height: 100%;
        }
      }
      .layout-right {
        padding-right: 20px;
        padding-left: 20px;
        position: absolute;
        right: 0;
        top: 0;
        background-color: #2d8cf0;
        z-index: 5;
        a {
          color: #fff;
        }
      }
    
      .ivu-menu-item-active {
        font-size: 20px;
      }
    }
    </style>
    
    

    效果:
    在这里插入图片描述
    B项目使用同样的方法配置文件。
    配置后效果如下:
    在这里插入图片描述

    到这里,我们就基本实现了分模块运行以及集体运行了。

    下面看一下打包。
    在分别运行了B项目和common的打包命令以后,效果正常。
    在这里插入图片描述
    另外,我在这里采用了iframe的方式嵌入了其他项目,是因为引入的方式打包的时候会打包太多。

    这样做的好处就是公共项目仅仅作为一个外壳使用,其他项目与其并没有太多的关联,保证了每个项目模块的独立性。


    四、demo地址

    https://github.com/Oralinge/pointsmodule


    以上。

    展开全文
  • vue电商后台管理系统

    2019-04-24 12:08:41
    电商后台管理系统的前端项目,基于Vue+Element实现。 主要包括商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等功能
  • 此Python+Django+VUE后台管理系统。包括的功能是用户管理----用户组管理的 增删该查功能。其中mysql数据库表的信息user_group.sql,也放到项目文件夹里了。
  • 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、...
  • Vue+springboot简单实现点餐系统开发, 项目进行前后端分离 后端采用springboot+mybatis+mysql数据库提供数据接口 前端采用Vue框架获取数据实现页面数据渲染、页面路由
  • (http://echarts.baidu.com/)、图片上传(头像上传返回上传路径,图上传返回上传路径、上传头像图片为base64、上传的图为base64)、字体图标库[fontawesome](http://www.fontawesome.com.cn/)、[vue-easytable]...
  • vue2+element-ui后台管理系统vue2+element-ui后台管理系统vue2+element-ui后台管理系统
  • 基于SpringBoot+MyBatis+Vue的人事管理系统
  • vue3.0+Ant Design Vue后台crm管理系统admin

    千人学习 2021-03-06 11:09:55
    使用了Vue3.0全家桶、ant-design-vue2.0,实践vue3.0的新特性以及玩法,vue3.0的Composition API相比于vue2.0的Options API 灵活很,让我们可以灵活地组合组件逻辑,目前后端admin大部分还是vue2.6;但是未来被vue3...
  • vuecli实战商城后台管理系统

    千人学习 2020-03-07 21:07:08
    elementUI实战开发商城后台管理系统完整视频教程,其中包括vuex模块化管理、Vue-router二次封装、使用element-ui库、支付模块、权限管理、商品规格实现、对象存储、api接口安全以及部署服务器上线等知识等。...
  • vue2+elementUI后台管理系统,页面源代码,src和static目录
  • 前端采用vue.js框架,后端采用springboot+mybatis框架开发的一套酒店管理系统,附带mysql脚本,酒店管理系统前端和后端分离部署,便于维护,提高工作效率
  • vue2.0 图书管理系统,毕业设计,实习项目,免费赠送,价值1999元的资料免费送
  • 是基于Spring Boot、Shiro和Vue等技术进行开发,主要是对后台管理系统常用模块前后端整体抽取构建成通用模板。也是集中对权限管理进行再次封装,以至于简单操作,便于二次开发代码重复。主要实现管理员管理、角色...
  • 利用iview脚手架Cli和vue2.0搭建的后台管理系统 利用iview脚手架Cli和vue2.0搭建的后台管理系统利用iview脚手架Cli和vue2.0搭建的后台管理系统
  • 本课程从0到1实现一个基于SpringBoot+Jpa+JWT+Spring Security+Vue+ElementUI整合前后端分离权限后台管理系统,数据库采用的是:mysql5.7,本项目主要功能模块有:用户管理、角色管理、菜单管理、部门管理、岗位管理...
  • 为什么我在本地写demo很顺,项目实战的时候却问题不断? 知识点掌握的再好,没有实战经验,实际工作中也免不了频频碰壁
  • 等技术栈开发的项目,采用分布式,模块,前后端分离开发。包括图形展示、权限管理、用户管理等功能。 【后端技术】 技术 说明 Spring Boot2 MVC框架 开发的一站式解决方案 Spring Security5  ...
  • 项目采用SpringBoot+Vue开发。 ## 后端技术栈 1.SpringBoot 2.SpringSecurity 3.MyBatis 4.MySQL ## 前端技术栈 1.Vue 2.ElementUI 3.axios 4.vue-router 具体详细配置以及运行请参照压缩包里的readme....
  • vue 管理系统顶部tags浏览历史实现

    千次阅读 2021-12-22 18:09:52
    动态判断tags长,放不下时,出现左右两侧按钮,减少时自动消失 动态判断窗口放大缩小,自动判断有无左右两侧按钮 正文 不用任何vuex,乱七八糟的方法,全在一个文件,粘贴即用 放到你想要的位置即可(此demo,放在...

    废话

    demo预览
    在这里插入图片描述

    在这里插入图片描述

    完成了哪些

    1. 默认有首页,不能关闭
    2. 点击路由菜单,判断有无存在,没有就添加,有就定位到上面
    3. 点击跳转,点击X可关闭
    4. 关闭当前页,自动跳到下一个tag页面
    5. 如果当前页在最后一个,默认跳到上一个tag页面
    6. 右键菜单,刷新,关闭右侧,关闭所有
    7. 动态判断tags长多,放不下时,出现左右两侧按钮,减少时自动消失
    8. 动态判断窗口放大缩小,自动判断有无左右两侧按钮

    正文

    不用任何vuex,乱七八糟的方法,全在一个文件,粘贴即用
    在这里插入图片描述
    放到你想要的位置即可(此demo,放在了面包屑上面)

    先安装 (监听某dom元素大小的包)

    npm install element-resize-detector
    

    tags.vue

    <template>
      <div>
        <div class="tags">
          <!-- 左箭头 -->
          <div
            class="arrow arrow_left"
            v-show="arrowVisible"
            @click="handleClickToLeft"
          >
            <i class="el-icon-arrow-left"></i>
          </div>
          <!-- 标签内容 -->
          <div class="tags_content" ref="box">
            <span ref="tags">
              <el-tag
                v-for="(tag, index) in tags"
                :key="tag.name"
                :class="[active == index ? 'active top_tags' : 'top_tags']"
                effect="dark"
                :closable="tag.name != 'Firstpage1'"
                @close="handleClose(index, tag)"
                @click="clickTag(index, tag)"
                @contextmenu.native.prevent="handleClickContextMenu(index, tag)"
              >
                {{ $t("router." + tag.name) }}
              </el-tag>
            </span>
          </div>
          <!-- 右箭头 -->
          <div
            class="arrow arrow_right"
            v-show="arrowVisible"
            @click="handleClickToRight"
          >
            <i class="el-icon-arrow-right"></i>
          </div>
        </div>
        <!-- 右键菜单 -->
        <ul
          v-show="contextMenu.isShow"
          :style="{ left: contextMenu.menuLeft, top: '96px' }"
          class="el-dropdown-menu el-popper"
          x-placement="bottom-end"
        >
          <li
            v-if="this.active == this.contextMenu.index"
            class="el-dropdown-menu__item"
            @click="refresh"
          >
            刷新
          </li>
          <li class="el-dropdown-menu__item" @click="closeRightTag">
            关闭右侧
          </li>
          <li class="el-dropdown-menu__item" @click="closeOtherTag">
            关闭其它
          </li>
          <div x-arrow="" class="popper__arrow" style="left: 44px;"></div>
        </ul>
      </div>
    </template>
    
    <script>
    import elementResizeDetectorMaker from "element-resize-detector";
    export default {
      data() {
        return {
          // 是否有箭头
          arrowVisible: true,
          // 点击次数
          num: 0,
          active: 0,
          tags: [],
          // 右键的元素
          contextMenu: {
            index: 0,
            tag: {},
            menuLeft: 0,
            isShow: false
          }
        };
      },
      watch: {
        $route() {
          this.getThisPage();
        },
        tags() {
          this.listenFun(this.$refs.tags, "tags");
        }
      },
      mounted() {
        this.listenFun(this.$refs.box, "box");
        var that = this;
        document.addEventListener("click", function(e) {
          that.contextMenu.isShow = false;
        });
      },
      methods: {
        // 监听可视区域宽,浏览器窗口大小改变执行
        listenFun(monitor, dom) {
          let boxWidth = this.$refs.box.offsetWidth,
            tagsWidth = this.$refs.tags.offsetWidth,
            erd = elementResizeDetectorMaker();
          erd.listenTo(monitor, ele => {
            this.$nextTick(() => {
              if (
                (dom == "box" && ele.offsetWidth >= tagsWidth) ||
                (dom == "tags" && ele.offsetWidth <= boxWidth)
              ) {
                this.arrowVisible = false;
                this.$refs.box.style.paddingLeft = "16px";
                this.$refs.box.style.paddingRight = "16px";
                this.$refs.box.style.transform = "TranslateX(0px)";
                this.num = 0;
              } else {
                this.arrowVisible = true;
                this.$refs.box.style.paddingLeft = "56px";
                this.$refs.box.style.paddingRight = "56px";
              }
            });
          });
        },
        // 判断当前页
        getThisPage() {
          let currentPgae = this.$route;
          // 判断tags里是否有当前页面
          var index = this.tags.findIndex(tag => tag.name == currentPgae.name);
          if (index == -1) {
            this.tags.push({
              name: currentPgae.name,
              path: currentPgae.path
            });
          }
          // 当前选择页
          this.active = this.tags.findIndex(tag => tag.name == currentPgae.name);
        },
        // 关闭标签
        handleClose(index, tag) {
          this.tags.splice(this.tags.indexOf(tag), 1);
          if (index == this.tags.length) {
            this.active = index - 1;
            this.$router.push(this.tags[index - 1].path);
          } else {
            this.$router.push(this.tags[index].path);
          }
        },
        // 点击标签
        clickTag(index, tag) {
          this.active = index;
          this.$router.push(tag.path);
        },
        // 左侧按钮
        handleClickToLeft() {
          if (this.num > 0) {
            this.num--;
            this.$refs.box.style.transform = `TranslateX(-${this.num * 200}px)`;
          }
        },
        // 右侧按钮
        handleClickToRight() {
          // 最后一个标签右测距离浏览器左侧距离
          let lastChild = document
            .querySelectorAll(".top_tags")
            [this.tags.length - 1].getBoundingClientRect().right;
          // 可视窗口的宽
          let bodyWidth = document.body.offsetWidth;
          // 右侧箭头48+右侧边距16
          if (bodyWidth - lastChild <= 64) {
            this.num++;
            this.$refs.box.style.transform = `TranslateX(-${this.num * 200}px)`;
          }
        },
        // 右键
        handleClickContextMenu(index, tag) {
          this.contextMenu.isShow = true;
          this.contextMenu.index = index;
          this.contextMenu.tag = tag;
          let isTag = document
            .querySelectorAll(".top_tags")
            [index].getBoundingClientRect();
          this.contextMenu.menuLeft = isTag.left - 48 + isTag.width / 2 + "px";
        },
        // 刷新
        refresh() {
          this.$router.go(0);
        },
        // 关闭其他
        closeOtherTag() {
          let tagsLin = this.tags.length,
            { index, tag, menuLeft } = this.contextMenu;
          if (index != 0) {
            this.tags = [
              {
                name: "Firstpage1",
                path: "/First/page1"
              },
              {
                name: tag.name,
                path: tag.path
              }
            ];
          } else {
            this.tags = [
              {
                name: "Firstpage1",
                path: "/First/page1"
              }
            ];
          }
          this.active = index;
          this.$router.push(tag.path);
        },
        // 关闭右侧
        closeRightTag() {
          let tagsLin = this.tags.length,
            { index, tag, menuLeft } = this.contextMenu;
          this.tags.splice(index + 1, tagsLin - index);
          this.active = index;
          this.$router.push(tag.path);
        }
      },
      created() {
        // 监听页面刷新
        window.addEventListener("beforeunload", e => {
          localStorage.setItem(
            "tagInfo",
            JSON.stringify({
              active: this.active,
              tags: this.tags
            })
          );
        });
        let tagInfo = localStorage.getItem("tagInfo")
          ? JSON.parse(localStorage.getItem("tagInfo"))
          : {
              active: 0,
              tags: [
                {
                  name: "Firstpage1",
                  path: "/First/page1"
                }
              ]
            };
        this.active = tagInfo.active;
        this.tags = tagInfo.tags;
      }
    };
    </script>
    <style lang="less" scoped>
    /deep/.el-tag--dark {
      border-color: transparent;
    }
    /deep/.el-tag--dark .el-tag__close {
      color: #86909c;
      font-size: 16px;
    }
    /deep/.el-tag--dark .el-tag__close:hover {
      background: #e7eaf0;
    }
    .tags {
      position: relative;
      overflow: hidden;
      .arrow {
        width: 48px;
        text-align: center;
        cursor: pointer;
        background: #fff;
        position: absolute;
        z-index: 1;
        &_left {
          left: 0;
          top: 0;
        }
        &_right {
          right: 0;
          top: 0;
        }
      }
      &_content {
        transition: 0.3s;
        white-space: nowrap;
        // padding: 0 16px;
      }
      .top_tags {
        margin-right: 8px;
        cursor: pointer;
        background: #fff;
        font-size: 12px;
        font-weight: 400;
        color: #1d2129;
      }
      .top_tags:hover,
      .active,
      .arrow:hover {
        background: #e7eaf0;
      }
    }
    </style>
    
    

    重点

    需要修改的地方
    在这里插入图片描述

    currentPgae.name 是路由结构的name,判断有无存在,没有就添加,有就定位到上面,根据项目修改
    在这里插入图片描述
    监听刷新时,去本地存储 tags 和 当前页面的active,Ftistpage1 改成自己的首页即可

    笔记

    getBoundingClientRect()介绍

    tab版的同样功能 完善了自动定位当前元素,推荐使用

    展开全文
  • vue axios css js element 2、项目结构 config中可以修改后端请求地址及端口 api封装了后端接口 components中包含了各种业务页面 router中是页面路由的配置 static中包含了多种静态文件 3、页面截图 登录首页,...

    转载地址:
    (vue管理系统)vue系统-毕设级项目搭建-vue博客系统(内含源码,vue博客前台+java逻辑后台+vue管理系统)
    转载请注明出处

    作者:Happy王子乐
    个人网站(整理了部分学习资源,以及个人项目):http://www.demxy.com/#/
    个人GitHub(喜欢的还请点个Star、flow一下):https://github.com/HappyWjl
    相关文章:
    (微信小程序)微信小程序-毕设级项目搭建-微信阅读小程序(内含源码,微信小程序+java逻辑后台+vue管理系统)~不求完美,实现就好
    (JAVA后端)微信小程序-毕设级项目搭建-微信阅读小程序(内含源码,微信小程序+java逻辑后台+vue管理系统)~不求完美,实现就好
    (vue管理系统)微信小程序-毕设级项目搭建-微信阅读小程序(内含源码,微信小程序+java逻辑后台+vue管理系统)~不求完美,实现就好
    (vue管理系统)微信小程序-毕设级项目搭建-微信小程序商城(内含源码,微信小程序+java逻辑后台+vue管理系统)~不求完美,实现就好
    (JAVA后端)微信小程序-毕设级项目搭建-微信小程序商城(内含源码,微信小程序+java逻辑后台+vue管理系统)
    (vue博客前台)vue系统-毕设级项目搭建-vue博客系统(内含源码,vue博客前台+java逻辑后台+vue管理系统)
    (java逻辑后台)vue系统-毕设级项目搭建-vue博客系统(内含源码,vue博客前台+java逻辑后台+vue管理系统)
    (vue管理系统)vue系统-毕设级项目搭建-vue博客系统(内含源码,vue博客前台+java逻辑后台+vue管理系统)
    (微信小程序)微信小程序-毕设级项目搭建-微信小程序商城(内含源码,微信小程序+java逻辑后台+vue管理系统)

    1、项目技术栈

    • vue
    • axios
    • css
    • js
    • element

    2、项目结构

    在这里插入图片描述

    • config中可以修改后端请求地址及端口
    • api封装了后端接口
    • components中包含了各种业务页面
    • router中是页面路由的配置
    • static中包含了多种静态文件

    3、页面截图

    • 登录首页,默认账号admin,密码admin
      在这里插入图片描述
    • 登录后主页
      在这里插入图片描述
    • 文章管理页,可以对文章进行筛选、编辑、修改、删除等操作,并支持多种文章格式。
      在这里插入图片描述
      在这里插入图片描述
    • 文章标签页,可对文章标签进行编辑、删除操作
      在这里插入图片描述
    • 文章类型管理页,可对文章类型进行编辑、删除操作
      在这里插入图片描述
    • 个人设置页,可进行登录账号修改
      在这里插入图片描述

    4、如何安装环境,以及部署

    • 详见统一博客,vue项目安装及部署:https://blog.csdn.net/u012888052/article/details/88377216

    以上,讲解地址:

    vue博客前台:https://blog.csdn.net/u012888052/article/details/95021871

    java后台项目讲解地址:https://blog.csdn.net/u012888052/article/details/95024099

    vue管理系统讲解地址:https://blog.csdn.net/u012888052/article/details/95020614


    作者:Happy王子乐

    展开全文
  • 基于webpack4.0 搭建vue多模块系统

    千次阅读 2019-03-14 22:04:54
    基于webpack4.0 搭建vue多模块系统。 当一个系统包含个模块时,总不能每个模块开一个vue项目吧,做不到资源共用,通过改造webpack配置来聚合个模块,达到资源共用的效果。 在config/index.js中配置相关的...
  • 一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库 丰富的组件,支持表单、文件上传、富文本.
  • 基于VUE的后台管理系统

    千次阅读 2021-03-28 10:27:18
    一、vue-element-admin github地址: https://github.com/PanJiaChen/vue-element-admin 文档地址:https://panjiachen.gitee.io/vue-element-admin-site/zh/ 预览地址:...
  • Vue后台管理系统模板推荐

    千次阅读 2021-03-11 17:07:06
    目前比较流行和 Vue 搭配的 UI组件 有Element-UI、iview、Bootstrap-Vue、Ant-Design-Vue,另外还有Vuetify、Buefy (Bulma css)、Vue Material 等等。基于这些组件库封装的后台管理模板,推荐一些常用 VUE后台模板
  • Springboot+Vue成果统一管理系统

    千次阅读 2021-12-28 20:14:51
    本项目是一个成果统一管理系统,用户在注册登录之后可以进行成果录入,主题支撑材料分析,成果支撑研究方向聚类分析,成果导出,以及对录入成果进行编辑修改。 其次,还包括对用户的资料管理功能,密码, 用户名的...
  • Vue模块系统

    千次阅读 2019-04-09 19:28:40
    在很 Vue 项目开发中,常规做法:1. 定义组件, 2. 使用组件(如下代码) //定义全局组件 Vue.component('my-component',{}); // 在模板中使用组件 new Vue({ el: '#app ' template:'<div><my-...
  • Vue项目:学生管理系统

    万次阅读 多人点赞 2022-02-28 21:54:54
    我们的Vue学生管理系统就结束了 欢迎大家添加博主交流 练习过程中遇到问题也可以提供支持 如果需要学习资料 博主也可以推荐 最后 如果觉得文章对您有帮助 请给博主点赞、收藏、关注 博主会不断推出更优质文章
  • 教学妹开发springboot+vue的博客论坛系统,so esay

    千次阅读 多人点赞 2022-04-21 16:02:27
    基于springboot+vue的博客论坛系统,如果你想学习更的项目源码,可以在文章的末尾领取源码资料。 当然前面已经开源了很的项目源码,都是免费学习的: 1,挑战一天开发一个前后端小程序系统|源码公开,开箱即用 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 159,518
精华内容 63,807
关键字:

vue 多系统