学习一款基于Vue2的极简后台管理系统模板:vue-admin-template

文章分类:Project 标签:后台管理系统 作者:Hackyle

更新时间:Thu Jan 12 17:54:31 CST 2023

本文是一篇我在学习vue-admin-template项目时的笔记,可以帮助读者快速掌握该项目的核心思想

vue-admin-template是什么?

  • 是一款基于Vue2的极简后台管理系统,只含前端。
  • 只包含了 Element UI & axios & iconfont & permission control & lint,这些搭建后台必要的东西。
  • 项目作者以及地址:https://github.com/PanJiaChen/vue-admin-template

背景

  • vue-admin-template这个项目很适合初学者学习
  • 因为它足够的简单,设计清晰,可以帮助初学者快速建立基于Vue的项目概念和一般项目的设计思想。可以基于该项目,快速构建起一个后台管理管理系统(前端)
  • 我在学习这个项目的过程中,对于一些我不是很熟悉的技术,需要在源码上写一些注释 ,对于作者为什么这么设计、代码为什么这样写 ,也会写一些我的思考、设计说明
  • 所以我克隆了该项目,将我的代码注释提交于Github,我对项目的一些思考与设计说明记录在本文中

强烈建议读者先阅读原作者的ReadMe

本文内容导览

克隆项目

Source Code

  • 原作者:https://github.com/PanJiaChen/vue-admin-template/
  • 我在原作者的源码上添加了用于学习的注释:https://github.com/HackyleShawe/vue-admin-template_4_learn

原作者提供的Demo

检查项目的依赖源

依赖安装:进入项目根目录,执行:npm install

项目结构

├── build                      // 构建相关
├── config                     // 配置相关
├── src                        // 源代码
│   ├── api                    // 所有请求
│   ├── assets                 // 主题 字体等静态资源
│   ├── components             // 全局公用组件
│   ├── directive              // 全局指令
│   ├── filtres                // 全局 filter
│   ├── icons                  // 项目所有 svg icons
│   ├── lang                   // 国际化 language
│   ├── mock                   // 项目mock 模拟数据
│   ├── router                 // 路由
│   ├── store                  // 全局 store管理
│   ├── styles                 // 全局样式
│   ├── utils                  // 全局公用方法
│   ├── views                   // 具体页面
│   ├── App.vue                // 入口页面
│   ├── main.js                // 入口 加载组件 初始化等
│   └── permission.js          // 权限管理
├── static                     // 第三方不打包资源
└── package.json               // 依赖管理

components

  • 放置的都是全局公用的一些组件,如上传组件,富文本等等
  • 一些页面级的组件建议还是放在各自views文件下,方便管理

views 和 api

  • 根据业务模块来划分 views,并且 将views 和 api 两个模块一一对应,从而方便维护

  • 一些全区公用的api模块,如七牛upload,remoteSearch等等,这些单独放置就行

封装axios

axios使用步骤

  • 配置axios的全局参数,初始化axios
  • 请求、响应拦截器
  • 写GET/POST/PUT/PATCH/DELETE请求

定义axios

import axios from 'axios'
import { Message } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'

// 创建axios实例
const service = axios.create({
  baseURL: process.env.BASE_API, // api的base_url
  timeout: 5000 // 请求超时时间
})

// request拦截器::从Cookie中获取token,放在请求头里
service.interceptors.request.use(config => {
  // Do something before request is sent
  if (store.getters.token) {
    config.headers['X-Token'] = getToken() // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
  }
  return config
}, error => {
  // Do something with request error
  console.log(error) // for debug
  Promise.reject(error)
})

// respone拦截器::根据后端定义的响应状态码,判断此次请求是否响应成功
service.interceptors.response.use(
  response => response,
  /**
   * 下面的注释为通过response自定义code来标示请求状态,当code返回如下情况为权限有问题,登出并返回到登录页
   * 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
   */
    //  const res = response.data;
    //     if (res.code !== 20000) {
    //       Message({
    //         message: res.message,
    //         type: 'error',
    //         duration: 5 * 1000
    //       });
    //       // 50008:非法的token; 50012:其他客户端登录了;  50014:Token 过期了;
    //       if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
    //         MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
    //           confirmButtonText: '重新登录',
    //           cancelButtonText: '取消',
    //           type: 'warning'
    //         }).then(() => {
    //           store.dispatch('FedLogOut').then(() => {
    //             location.reload();// 为了重新实例化vue-router对象 避免bug
    //           });
    //         })
    //       }
    //       return Promise.reject('error');
    //     } else {
    //       return response.data;
    //     }
  error => {
    console.log('err' + error)// for debug
    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    })
    return Promise.reject(error)
  })

export default service

使用axios

import request from '@/utils/request'

//使用
export function getInfo(params) {
  return request({
    url: '/user/info',
    method: 'get',
    params
  });
}

webpack-alias

  • 当项目逐渐变大之后,文件与文件直接的引用关系会很复杂,这时候就需要使用alias 了。
  • 有的人喜欢alias 指向src目录下,再使用相对路径找文件
  • @ 是 webpack 的 alias ,代表当前项目的src目录
  • 在Vue项目配置文件config.js中定义alias

页面结构Layout

  •  在src/layout/目录下定义页面的主体结构

  • 在src/router/中的每个路由定义为:
    • 将每个顶级路由的路由页面为:src/layout;
    • 每个子路由的路由页面为:子路由的页面

项目主页:src/layout/index.vue

  • vue-element-admin 中大部分页面都是基于这个 layout 的,除了个别页面如:login , 404, 401 等页面没有使用该layout。
  • 等价于其他项目中的vue组件
  • 如果你想在一个项目中有多种不同的layout也是很方便的,只要在一级路由那里选择不同的layout组件就行。

src/layout/components/AppMain.vue

  • 功能:在vue组件中展示子路由页面
  • <router-view>为子路由的占位符,<keep-alive>用于保存切换了Tab页后依然保存了上个页面上的数据,配合页面的 tabs-view 标签导航使用

左侧导航栏Sidebar

@/layout/components/sidebar/index.vue

Header

@/layout/components/Navbar.vue

多级导航/路由

什么是多级路由

如何实现多级路由:src/router/index.js

store

vuex

  • 数据存储、传递工具
  • 是专门为 Vue 开发的状态管理方案,我们可以把需要在各个组件中传递使用的变量、方法定义在这里

使用步骤

  • 挂载Vuex,定义Store模型:src/store/index.js
  • 加载Store,在src/main.js中导入
  • 放入数据:$store.commit(mutations函数名,参数)
  • 读取数据:$store.state.State中的数据名

store的基本结构

  • state:要全局共享的属性,全局只存在一份
  • getter:实时监听state属性的变化,并返回
  • mutation:提供更改state中的属性的方法
  • action:一些业务代码,并且可以提交用于mutation,目的还是为了更改state中的值

 store/index.js

  • vuex的入口文件
  • 模块化管理vuex,引入其他的vuex组件JS文件

store/getters.js

  • 将store/modules中的所有JS文件中的state属性值聚合
  • 提供类似于getter的操作,实时获取整个vuex中的所有属性

store/modules模块化管理vuex

  • app.js:全局存储共享本个项目的全局配置信息
  • settings.js:全局存储共享本个项目的自定义配置项
  • user.js:全局存储共享用户的登录信息(用户名称、token、头像URL)

登录

  • 登录(认证)的主要思路:
    • 当用户填写完账号和密码后向后端验证是否正确,验证通过之后,后端会返回一个token,拿到token之后(我会将这个token存贮到cookie中,保证刷新页面后能记住用户登录状态)
    • 前端会根据token再去后端请求一个 user_info 的接口来获取用户的详细信息(如用户权限,用户名等等信息)。
  • 权限验证的主要思路:根据后端返回的当前用户的role,动态地算出其对应有权限的路由,通过 addRoutes 动态挂载这些路由。

登录页:src/views/login/index.vue

  1. 一个表单:用户名输入框、密码输入框、提交按钮
  2. 在向服务端提交之前对账号和密码做一次简单的规则校验
  3. 将登录按钮上绑上click事件,点击登录之后向服务端提交账号和密码进行验证

为什么要将调用登录API的动作代码放于store/modules/user.js中?

  • 使用vuex来全局共享用户成功的登录信息
  • 为了便于将登录成功的用户信息塞入veux,直接在store的代码中定义调用后端的用户登录、获取登录的用户信息、登出(清空vuex中的信息)的业务代码

store/modules/user.js的action函数

  • 登录:请求后端接口;成功后将token信息存储Cookie中
  • 获取用户信息:请求后端接口,获取用户的信息,填充到vuex
  • 登出:请求后端接口,移除本地Cookie中的Token,清除动态加载的路由,请求vuex中的数据

路由前置拦截器(router.beforeEach)

  • 每次路由都判断一下Cookie里有没有token
  • 如果没有跳转到登录页面
  • 如果有判断一下Vuex有没有用户信息:没有用户信息:请求后端接口获取;有用户信息:路由到想要的页面
  • 实现:src/permission.js

为什么不把用户信息也存放于Cookie,而每次都要向后端获取?

  • 保证获取到最新的用户信息,最关键的获取的最新的用户权限,通过用户权限动态挂载路由页面。
  • 假设这样一种场景,你在公司电脑上修改了权限,然后你用家用电脑登录,权限还是没有变化,要等待Cookie失效后,你家用电脑上的权限才会重新请求后端获取。
  • 当然如果是做了单点登录得功能的话,用户信息存储在本地也是可以的。当你一台电脑登录时,另一台会被提下线,所以总会重新登录获取最新的内容。

 

————————————————
版权声明:非明确标注皆为原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上本文链接及此声明。
原文链接:https://blog.hackyle.com/article/project/vue-admin-template-4-learn

留下你的评论

Name: 

Email: 

Link: 

TOP