从零到一搭建Vue2后台管理系统

本文将从零到一实现一个基于Vue2+ElementUI的后台管理系统,《项目地址》让我们开始吧!

1.创建项目

使用Vue CLI创建项目,一手vue create vue2-element-admin走起!

我这里是配置了几个常用的配置项目,没有配置也没有关系,总之就是一步步选择下来,要选择的有vue-router,vuex,node-sass,babel,eslint,回车,等待install完成即可。

进入到项目目录,yarn serve启动服务即可,这里有一个小技巧,就是在原本的serve命令最后添加--open ,即可在服务启动完成后自动在浏览器打开页面。

package.json 如下:
{  "name": "vue2-element-admin",  "version": "0.1.0",  "private": true,  "scripts": {    "serve": "vue-cli-service serve --open",    "build": "vue-cli-service build",    "lint": "vue-cli-service lint"  },  "dependencies": {    "core-js": "^3.6.5",    "vue": "^2.6.11",    "vue-router": "^3.2.0",    "vuex": "^3.4.0"  },  "devDependencies": {    "@vue/cli-plugin-babel": "~4.5.0",    "@vue/cli-plugin-eslint": "~4.5.0",    "@vue/cli-plugin-router": "~4.5.0",    "@vue/cli-plugin-vuex": "~4.5.0",    "@vue/cli-service": "~4.5.0",    "babel-eslint": "^10.1.0",    "eslint": "^6.7.2",    "eslint-plugin-vue": "^6.2.2",    "node-sass": "^4.12.0",    "sass-loader": "^8.0.2",    "vue-template-compiler": "^2.6.11"  }}
复制代码

接下来就是把不需要的文件及代码通通干掉,完成后项目目录如下:

2.新建vue.config.js,并添加基础配置

"use strict";const path = require("path");function resolve(dir) {  return path.join(__dirname, dir);}// 端口号const port = 8080;module.exports = {  // 部署应用包时的基本 URL  publicPath: "./",  // 项目打包输出目录  outputDir: "dist",  // 项目静态文件打包输出目录  assetsDir: "static",  // 是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码。这个值会在 @vue/cli-plugin-eslint 被安装之后生效。  lintOnSave: process.env.NODE_ENV === "development",  productionSourceMap: false,  devServer: {    port: port,    open: false,    https: false,    hotOnly: false,  },  configureWebpack: {    resolve: {      // 配置快捷路径      alias: {        "@": resolve("src")      }    },  },};
复制代码

3.引入ElementUI组件库

通过命令yarn add element-ui安装依赖,接下来在main.js添加以下代码,即可在项目中开心的使用ElemnetUI组件库了

import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI)
复制代码

4.基础页面编写

基本的页面包括首页,登录页面,以及基本的逻辑编写

这里对页面结构及样式不做过多赘述,只贴关键代码。

1.登录页面通过ElementUI的form组件编写即可,点击登录调用方法如下:

methods: {  login(formName) {    this.loginLoading = true;    this.$refs[formName].validate((valid) => {      if (valid) {        this.$store.dispatch("user/login", this.param).then(() => {          this.loginLoading = false;          this.$router.push({ name: "Home" });        });      } else {        return false;      }    });  },}
复制代码

登录请求的操作我们给到了store里的user模块的login action去处理,在user模块,维护了用户的信息,在登录操作成功后将用户信息保存在store中,代码如下:

actions: {  // 登录  login({commit,dispatch},data){    return new Promise((resolve) => {      apiLogin(data).then(async res => {        commit('SET_USER_INFO',res.body)        resolve('success')      })    })  }
}
复制代码

上面代码中,调用了apiLogin方法发起请求,实际项目中,我会把所有接口请求方法放在src目录下的api文件夹中,并为每个模块创建对应的js文件维护该模块接口。

登录过程需要发起接口请求,vue项目中通常使用axios库

5.安装axios

通过命令yarn add axios安装依赖,并在src目录下新建utils管理我们的工具方法

在utils目录下新建requeset.js,封装axios,并向外暴露axios实例,这里我们可以通过请求拦截器及响应拦截器编写通用逻辑,并组建基本的请求体结构。

在搭建项目的时候,很多时候还没有后端接口给到前端,为了整体逻辑更接近实际项目过程,我们需要使用mockjs

6.安装mockjs

通过命令yarn add mockjs安装依赖,并在项目根目录创建mock文件夹,mock文件夹下新建index.js,所有的请求接口都会通过index.js暴露,为了更好的管理我们的接口,用户操作相关的接口放在user.js文件中,并在index.js引入user.js,登录mock代码如下:

// 引入mockjsconst Mock = require('mockjs')// 登录Mock.mock('/api/user/login', 'post', (req) => {  const data = JSON.parse(req.body).body;  return {    header:{      code:0    },    body:{      busiId:'001',      name:data.name,      avatar:'https://img0.baidu.com/it/u=3233551726,336273710&fm=26&fmt=auto&gp=0.jpg'    }  }})
复制代码

引入mockjs需要在main.js添加如下代码:

// 如果是开发环境,引入mock

process.env.NODE_ENV==='development'&&require('../mock/index')
复制代码

至此,整个登录流程完成。

7.路由权限控制

通常,如果用户未登录的情况下访问后台管理系统且目标页面不是登录页面,需要将用户路由指向登录页面进行登录,这一步可以通过vue-router的路由前置守卫实现,代码如下:

// 路由前置守卫router.beforeEach((to,from,next) =>{  // 免登录白名单  const whiteList = ['Login','NotFund']  // 如果未登录 并且目标路由不在白名单  if(!store.getters.userInfo.userId&&whiteList.indexOf(to.name)===-1) next({name:'Login'})  else next()})
复制代码

这里我们用到了store.getters.userInfo.userId判断用户是否登录,实际项目中,大家可以根据实际项目需求进行该判断,比如判断cookie,seesion等。

并且在登录成功后,在store/permission中进行了动态路由的添加,模拟登录成功后,动态添加该用户的权限路由。

这里的getters我编写了一个getters.js文件在src/store目录下,统一管理strore的getters,并在store/index.js中引入使用,代码如下:

import Vue from 'vue'import Vuex from 'vuex'import getters from './getters'import user from './modules/user'Vue.use(Vuex)export default new Vuex.Store({  state: {  },  mutations: {  },  actions: {  },  getters,  modules: {    user  }})
复制代码

8.页面主体框架

后台管理系统的整理内容框架一般如下图所示:

左侧为logo及菜单区,右侧顶部为控制菜单展开收起的按钮,当前页面的面包屑导航,用户头像,点击下拉一般会有用户信息,修改密码,退出登录等快捷入口及操作,以及当前已打开页面的页签列表。

在系统内点击左侧菜单切换页面的时候,页面主体框架是不变的,只有中间内容区切换展示对应业务页面,很自然的想到这一部分可以抽离出一个组件进行维护,业务页面通过router-view标签嵌套在主体框架中。

在项目中,以上功能可以通过路由嵌套实现,调整后的首页路由如下:

{  path: '/',  name: 'Root',  redirect:'/home',  component: Layout,  children:[    {      path:'home',      name:"Home",      meta:{title:'首页},      component:() => import('@/views/Home.vue')    }  ]}
复制代码

上面的Layout即为封装好的主体框架组件,Home.vue代码如下:

<template>  <div class="home pt_20 t_center fontsize_20">    {{message}}  </div></template><script>export default {  name: "Home",  components: {},  data() {    return {      message:'Welcome to vue2-elment-admin by wzy'    };  },};</script>
复制代码

此时打开首页,即可看到如上图的首页内容。

接下来,我们就需要一步步编写Layout组件了

8-1.左侧logo

这一部分很简单,就是一个左右布局,并引入到左侧对应组件src/layout/components/SliderBar/index.vue中

8-2.左侧菜单

这一部分相对复杂一点,src/layout/components/SliderBar/index.vue为主体文件,使用el-menu组件,内部遍历routes,根据是否有子路由,选择使用el-submenu或者el-munu-item组件生成菜单,需要注意的是这里的Item组件需要给定内部,以便Item组件递归自调用时使用。

SliderBar文件目录如下:

这里要说一下el-menu组件有一个collapse属性,控制菜单的展开收起,我们再store的setting.js模块中维护了这个状态

8-3.右侧Collapse组件

该组件控制切换store下setting.js中collapse属性切换,对应文件位置如下:

8-4.右侧面包屑导航

该组件动态展示当前页面路由,且当前页面的祖先路由可以点击进行跳转,对应文件位置如下:

8-5.右侧头像下拉

该组件展示登录用户的头像,点击展开下拉,显示用户信息,修改密码,退出登录等功能,对应文件位置如下:

8-6:右侧已访问路由列表

改组件展示用户已经访问的路由,并且右键显示刷新,关闭,关闭其他,关闭所有菜单,功能相对复杂一些,对应数据状态存和修改数据方法放在store/tagsView中进行维护,对应文件位置如下:

通过路由后置守卫,将访问过的路由添加到store/tagsView中

至此,页面主体框架部分完成!

但是先不要高兴的太早,当登录成功进入首页后,一番操作,感觉十分丝滑,但是按下F5后,发现页面直接跳转到登录页面了,这是因为我们的项目是单页应用,登录信息放在了store下的user模块中,刷新后store中的数据进行了初始化,此时为未登录状态,所以被我们之前设置的路由守卫指向到了登录页面,解决这个问题,我们需要在store的引入过程中封装一下。

9.解决页面刷新丢失store数据问题

在src/utils目录下创建cacheStore.js文件,引入store,并尝试在sessionStorage获取缓存的store,如果有,则更新store,并且添加给window对象添加beforeunload方法,该方法会在页面刷新时触发,将store.state存放在sessionStorage进行缓存,最后导出store,这样,store.state中的数据会在刷新前进行缓存,并在页面刷新后进行读取合并,达到页面刷新不丢失数据的效果,代码如下:

import store from "@/store";// 在页面加载时读取sessionStorage里的状态信息const sessionStore = sessionStorage.getItem("store");if (sessionStore && sessionStore !== 'undefined') {  store.replaceState(Object.assign({}, store.state, JSON.parse(sessionStore)));  // 如果已经登录,刷新后初始化路由  if (store.getters.userInfo&&store.getters.userInfo.userId) {    store.dispatch('permission/handleRoutes')  }}//在页面刷新时将vuex里的信息保存到sessionStorage里window.addEventListener("beforeunload", () => {  sessionStorage.setItem("store", JSON.stringify(store.state));});export default store;
复制代码

main.js中store引入修改如下:

import store from '@/utils/cacheStore'
复制代码

登录成功后再次尝试刷新页面,发现一切OK了!

10.commit-msg校验添加

项目中,git commit 信息如果不做规范约束,回过头来查看的时候,有时候会一脸茫然,那么关于git commit 信息的校验怎么做呢?这里我们利用gitHooks中的对应钩子做commit-msg的校验,package,json配置如下:

"gitHooks": {  "commit-msg": "node script/verify-commit-msg.js",  "pre-commit": "vue-cli-service lint --fix"}
复制代码

可以看到,这里还利用了pre-commit钩子在commit之前做了 lint fix,

在commit-msg钩子中,执行了script/verify-commit-msg.js文件,该文件我照搬了尤大在vue中的校验文件,需要注意的是该校验依赖yorkie库,需要yarn add yorkie -D安装一下。

具体的校验规范大家可以自行了解一下,这里就不展开讲了,个人常用如下:

feat:新功能(feature)

fix:修补bug

docs:文档(documentation)

style: 格式(不影响代码运行的变动)

refactor:重构(即不是新增功能,也不是修改bug的代码变动)

test:增加测试

chore:构建过程或辅助工具的变动

End

至此,本文就结束了,项目中其他的细节还是需要在项目代码中具体查看,本文只是把主体思路及节点讲述一遍,如有任何问题或建议,欢迎留言讨论!

如果觉得文本不错或者对您有些许帮助,欢迎点赞或者github点个star、follow,十分感谢!

猜你喜欢

转载自juejin.im/post/7015537495945248804