介绍
vue-element-admin 是一个后台前端解决方案,它基于 vue 和 element-ui实现。它使用了最新的前端技术栈,内置了 i18 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你
- vue-element-admin定位是后台集成方案,不适合当基础模板进行二次开发,项目集成了许多用不到的功能,会造成代码沉余
- vue-admin-template是一个后台基础模板,建议使用此模板进行二次开发
- electron-vue-admin是一个桌面终端,如果进行桌面终端开发可以使用此模板
功能
- 登录 / 注销
- 权限验证
- 页面权限
- 指令权限
- 权限配置
- 二步登录
- 多环境发布
- dev sit stage prod
- 全局功能
- 国际化多语言
- 多种动态换肤
- 动态侧边栏(支持多级路由嵌套)
- 动态面包屑
- 快捷导航(标签页)
- Svg Sprite 图标
- 本地/后端 mock 数据
- Screenfull全屏
- 自适应收缩侧边栏
- 编辑器
- 富文本
- Markdown
- JSON 等多格式
- Excel
- 导出excel
- 导入excel
- 前端可视化excel
- 导出zip
- 表格
- 动态表格
- 拖拽表格
- 内联编辑
- 错误页面
- 401
- 404
- 組件
- 头像上传
- 返回顶部
- 拖拽Dialog
- 拖拽Select
- 拖拽看板
- 列表拖拽
- SplitPane
- Dropzone
- Sticky
- CountTo
- 综合实例
- 错误日志
- Dashboard
- 引导页
- ECharts 图表
- Clipboard(剪贴复制)
- Markdown2html
目录结构
├── build # 构建相关
├── mock # 项目mock 模拟数据
├── plop-templates # 基本模板
├── public # 静态资源
│ │── favicon.ico # favicon图标
│ └── index.html # html模板
├── src # 源代码
│ ├── api # 所有请求
│ ├── assets # 主题 字体等静态资源
│ ├── components # 全局公用组件
│ ├── directive # 全局指令
│ ├── filters # 全局 filter
│ ├── icons # 项目所有 svg icons
│ ├── lang # 国际化 language
│ ├── layout # 全局 layout
│ ├── router # 路由
│ ├── store # 全局 store管理
│ ├── styles # 全局样式
│ ├── utils # 全局公用方法
│ ├── vendor # 公用vendor
│ ├── views # views 所有页面
│ ├── App.vue # 入口页面
│ ├── main.js # 入口文件 加载组件 初始化等
│ └── permission.js # 权限管理
├── tests # 测试
├── .env.xxx # 环境变量配置
├── .eslintrc.js # eslint 配置项
├── .babelrc # babel-loader 配置
├── .travis.yml # 自动化CI配置
├── vue.config.js # vue-cli 配置
├── postcss.config.js # postcss 配置
└── package.json # package.json
安装
# 克隆项目
git clone https://github.com/PanJiaChen/vue-element-admin.git
# 进入项目目录
cd vue-element-admin
# 安装依赖
npm install
# 速度过慢可以使用下面方法进行指定下载镜像原
# 也可以使用nrm选择下载镜像原
# 建议不要用 cnpm 安装 会有各种诡异的bug 可以通过如下操作解决 npm 下载速度慢的问题
npm install --registry=https://registry.npm.taobao.org
# 注意:此框架启动和平常我们自己设置不同,要使用如下方法进行启动
# 本地开发 启动项目
npm run dev
启动完成后会自动打开浏览器访问 http://localhost:9527,可以看到页面就证明你操作成功了
layout布局
在大部分页面中都是基于layout的,除:404、login等没有使用到该布局
layout整合了页面所有布局进行分块展示
整个板块被分成了三部分
layout主要编排
Src目录下
入口文件 main.js
里面有用到自定义的mock文件访问,我们要将其注释掉
src下的mock文件夹建议删掉,我们后期不会用到
App.vue
src下,除了main.js还有两个文件,permission.js 和settings.js
permission.js
permission.js 是控制页面登录权限的文件,我们可以先将其全部注释掉,后期用到在慢慢添加
settings.js
settings.js则是对于一些项目信息的配置,里面有三个属性 **title(项目名称),fixedHeader(固定头部),sidebarLogo(显示左侧菜单logo)
其中的配置我们在其他地方会用到,不要去动
API模块和请求封装模块介绍
API模块的单独请求和 request模块的封装
Axios的拦截器
axios的拦截器原理:
通过create创建一个新的axios实例
// 创建了一个新的axios实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
})
请求拦截器
主要处理 token的_统一注入问题_
service.interceptors.request.use(
config => {
if (store.getters.token) {
config.headers['X-Token'] = getToken()
}
return config
},
error => {
return Promise.reject(error)
}
)
响应拦截器
处理 返回的数据异常 和_数据结构_问题
// 响应拦截器
service.interceptors.response.use(
response => {
const res = response.data
// if the custom code is not 20000, it is judged as an error.
// 自定义代码返回值是自己商量的,按照自己的需求来编写
if (res.code !== 20000) {
Message({
message: res.message || 'Error',
type: 'error',
duration: 5 * 1000
})
// 自定义代码返回值是自己商量的,按照自己的需求来编写
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// to re-login
MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
confirmButtonText: 'Re-Login',
cancelButtonText: 'Cancel',
type: 'warning'
}).then(() => {
store.dispatch('user/resetToken').then(() => {
location.reload()
})
})
}
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res
}
},
error => {
console.log('err' + error) // for debug
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
)
上面是在 src/utils/request.js下的源代码
我们只需要保留:
// 导出一个axios的实例 而且这个实例要有请求拦截器 响应拦截器
import axios from 'axios'
const service = axios.create() // 创建一个axios的实例
service.interceptors.request.use() // 请求拦截器
service.interceptors.response.use() // 响应拦截器
export default service // 导出axios实例
单独封装api
我们习惯将所有的api请求放到api目录下统一管理,按照模块进行划分使用
api/user.js
import request from '@/utils/request'
export function login(data) {
return request({
url: '/vue-admin-template/user/login',
method: 'post',
data
})
}
export function getInfo(token) {
return request({
url: '/vue-admin-template/user/info',
method: 'get',
params: { token }
})
}
export function logout() {
return request({
url: '/vue-admin-template/user/logout',
method: 'post'
})
}
我们只需保留如下代码,后期在进行添加
import request from '@/utils/request'
export function login(data) {
}
export function getInfo(token) {
}
export function logout() {
}
登录模块
设置固定的本地访问端口和网站名称
设置统一的本地访问端口和网站title
本地服务端口: 在vue.config.js中进行设置
vue.config.js 就是vue项目相关的编译,配置,打包,启动服务相关的配置文件,它的核心在于webpack,但是又不同于webpack,相当于改良版的webpack
我们看到上面是一个环境变量而不是实际地址,那么我们在哪设置了呢
在项目下我们会发现两个文件
development => 开发环境
production => 生产环境
当我们运行npm run dev进行开发调试的时候,此时会加载执行**.env.development**文件内容
当我们运行npm run build:prod进行生产环境打包的时候,会加载执行**.env.production**文件内容
如果想要设置开发环境的接口,直接在**.env.development**文件中写入对于变量直接赋值即可
# just a flag
ENV = 'development'
# base api
VUE_APP_BASE_API = 'api/private/v1/'
如果想要设置生产环境的接口**.env.production**文件中写入对于变量直接赋值即可
# just a flag
ENV = 'production'
# base api
VUE_APP_BASE_API = 'api/private/v1/'
网站名称
src/settings.js
中
title 就是网站名称
配置完我们要进行重启,否则有些配置不会生效
登录页面
设置头部名称:
<!-- 放置标题图片 @是设置的别名-->
<div class="title-container">
<h3 class="title">海豚电商后台管理平台</h3>
</div>
设置背景图片:
可根据需求更改
/* reset element-ui css */
.login-container {
background-image: url('~@/assets/common/bgc.jpg'); // 设置背景图片
background-position: center; // 将图片位置设置为充满整个屏幕
}
对应代码:
登录表单的校验
el-form表单校验的条件
用户名和密码的校验:
<el-form-item prop="username">
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
<el-input
ref="username"
v-model="loginForm.username"
v-focus
placeholder="Username"
name="username"
type="text"
tabindex="1"
auto-complete="on"
/>
</el-form-item>
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon-class="password" />
</span>
<el-input
:key="passwordType"
ref="password"
v-model="loginForm.password"
:type="passwordType"
placeholder="Password"
name="password"
tabindex="2"
auto-complete="on"
@keyup.enter.native="handleLogin"
/>
<span class="show-pwd" @click="showPwd">
<svg-icon
:icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
/>
</span>
</el-form-item>
const validateUsername = (rule, value, callback) => {
if (value.length < 5) {
callback(new Error('用户名最少5位'))
} else if (value.length > 12) {
callback(new Error('用户名最长12位'))
} else {
callback()
}
}
const validatePassword = (rule, value, callback) => {
if (value.length < 5) {
callback(new Error('用户名最少5位'))
} else if (value.length > 16) {
callback(new Error('用户名最长16位'))
} else {
callback()
}
}
loginRules: {
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
password: [
{ required: true, trigger: 'blur', validator: validatePassword },
{ min: 5, max: 12, trigger: 'blur', message: '密码长度应该在5-12位之间' }
]
}
Vue-Cli配置跨域代理
出现跨域的原因是什么呢?
因为当下流行的是前后端分离单独开发,前端项目和后端接口不在同域名之下,那前端访问后端接口就出现跨域了
那么问题就来了 如何解决呢?
我们所遇到的这种跨域是位于开发环境的,真正部署上线时的跨域是生产环境的,解决方式又不同
我们先解决开发环境,生产环境在打包上线事可以解决,后面再讲
解决开发环境的跨域问题
开发环境的跨域,也就是在vue-cli脚手架环境下开发启动服务时,我们访问接口所遇到的跨域问题,vue-cli为我们在本地开启了一个服务,可以通过这个服务帮我们代理请求,解决跨域问题
也就是vue-cli配置webpack的反向代理
在vue.config.js
中进行反向代理配置
module.exports = {
devServer: {
proxy: {
'api/private/v1/': {
target: 'http://127.0.0.1:8888', // 我们要代理的地址,当匹配到上面的'api/private/v1/'时,会将http://localhost:9528 替换成 http://127.0.0.1:8888
changeOrigin: true, // 是否跨越 需要设置此值为 true 才可以让本地服务代理我们发送请求
pathRewrite: {
// 重新路由 localhost:8888/api/login => http://127.0.0.1:8888/api/login
'^/api': '/api',
'/hr': ''
}
}
}
}
}
同时,还需要注意的是,我们同时需要注释掉 mock的加载,因为mock-server会导致代理服务的异常
// before: require('./mock/mock-server.js'), // 注释mock-server加载
封装单独的登录接口
export function login(data) {
// 返回一个axios对象 => promise // 返回了一个promise对象
return request({
url: 'login', // 因为所有的接口都要跨域 表示所有的接口要带 /api
method: 'post',
data
})
}