在线预览地址:
#/仪表板
前言
制作这个 vueAdmin-template 的主要原因是: vue-element-admin 项目的初衷是 Vue 管理后端集成解决方案。 与您分享一些常用的组件或经验。 同时也在不断的维护和扩展的过程中,比如最近搭建了dashboard,增加了全屏功能,增加了tabs-view等。因此,项目将变得越来越复杂,不适合很多刚接触Vue的朋友搭建后端。 所以我写了这个基本模板。 它没有复杂的功能,只包含了后台需要的最基本的东西。 vueAdmin-template主要基于vue-cliwebpack模板开发,引入了以下依赖:
本项目仅提供极简的管理后端功能,封装axios请求,支持无限级别的路由、动态权限和动态侧边栏。 如果需要更复杂的功能,可以参考vue-element-admin。 如果仍然存在缺陷,请提交问题或 PR。 下面简单说一下使用这个模板时需要注意的事项。
路由延迟加载
路由延迟加载应该是编写较大项目时使用的功能。 只有使用该组件时才会加载相应的组件。 这样的写法大大减少了初始页面js的大小,可以更好的使用浏览。 服务器缓存。
const Foo = resolve => require(['./Foo.vue'], resolve)
//或者
const Foo = () => import('./Foo');
当懒加载页面不多的时候一切都是那么的美妙,但是我们公司的后端业务却在不断的迭代。 目前该项目已拥有近百条航线。 这时,在开发模式下使用路由的延迟加载是一件令人沮丧的事情。 光是改一行代码热更新就需要6000ms+,这让我怎么忍心。 发帖人花了三天多的时间寻找原因。 他尝试了所有优化 webpack 的方法,包括 DLL、HappyPack 等方法,但改进并不是很显着。 Webpack 3 恰好在那个时候发布。 升级后,编译速度也得到了很大的提升,但仍然需要2000ms+。 。 后来通过专家@jzlxiaohei的建议,发现是路由懒加载导致的。 作者猜测异步加载可能会导致webpack的缓存每次都失败,所以每次重建都会这么慢。 一旦找到原因,我们就可以对症下药了。 我们自己封装了一个 _import() 方法,并且只在直接环境中使用延迟加载。 这解决了令人困惑且麻烦的缓慢重建问题。代码
const _import = require('./_import_' + process.env.NODE_ENV);
const Foo = _import('Foo');
比原来的6000ms快了十几倍,终于又可以愉快的开发了。
权限控制
本章我将带大家使用vue玩转后端系列2(登录权限),已经详细介绍过。 本项目中权限的实现方法是获取当前用户的权限来对比路由表,生成当前用户权限可访问的路由表,并通过router.addRoutes动态挂载到路由器上。 不过虽然很多公司的业务逻辑可能不是这样,但举个反例,很多公司都要求动态配置每个页面的权限,而不像本项目中是硬编码预设的。 但虽然原理是一样的。 就像这个反例一样elementui替换样式,你可以在后台通过树形控件或者其他解释方式动态配置每个页面的权限,然后将这个路由表存储在前端。 当用户登录并按下角色时,前端返回对应的路由表或者后端请求之前存储的路由表动态生成可访问的页面,然后router.addRoutes动态挂载到路由器上。 你会发现,原来是一样的,从来没有背离过它的本源。
导航
Sidebar:本项目中的侧边栏是根据router.js配置的路由,根据权限动态生成的。 这样就省去了写路由和自动写侧边栏的麻烦。 它还使用了 Recursive 组件,这样无论你的路由有多少层嵌套,都可以愉快地显示。 权限验证也是递归完成的。
蛋糕屑:这个项目还封装了一个蛋糕屑导航,也是通过watch$route.code动态生成的
因为侧边栏导航,蛋糕屑,或者权限,你会发现它们似乎都和router密切相关,所以我们在vue-router路由信息对象的基础上做了一个小扩展,定制了一些属性。
您还可以根据您的业务需求添加和修改此自定义属性。
图标字体
element-ui自带的图标不是很丰富,但是管理后台图标非常可定制。 这里我只推荐大家使用阿里巴巴的iconfontelementui替换样式,简单易用,易于管理。 本项目中已经嵌入了一些iconfont作为反例,您可以自行替换。 这里简单介绍一下iconfont的使用方法。 首先,注册了iconfont账户后,你就可以在我的项目中管理自己的iconfont了。 我们公司的所有项目都是使用这个系统进行管理的,我强烈推荐使用它。
创建完图标库后,更新替换也非常方便。 这里我使用Symbol形式导入。 还有 unicode 和 font-class 导入形式。 有兴趣的可以自己研究一下。以后我们点击下载Symbol的时候,会发现有一个像下面这样的文件。 我们只需要关心iconfont.js。
我们只需替换项目中的iconfont.js即可。 为了方便起见,该项目还封装了一个 svg 组件。
<icon-svg icon-class="填入你需要的iconfont名字就能使用了">
图标
每个项目都需要有自己的网站图标。
虽然实现起来很方便,但是我们主要需要使用html-webpack-plugin
//webpack config
function resolveApp(relativePath) {
return path.resolve(relativePath);
}
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
favicon: resolveApp('favicon.ico')
}),
你只需要把这个项目和目录下的favicon.ico文件替换成你想要的图标即可。
埃斯林特
Vuecli 默认提供两种 lint 规范:standard 和 airbnb。 说实话,一个j检测校准太松,另一个太软,而且每个团队的lint规范都不同,所以笔者简单的使用了项目中常用的大部分。 列出并注释了 lint 规范,以方便您更改代码地址。 您还可以将自己的规范上传到 npm,例如 vue、vue-eslint-config。 配置eslint对于多人协作项目非常有用。 同时配置lint,添加ide的lint插件来写代码就起飞了。 相关配置可以参见第一篇教程。
后CSS
相信大部分vue项目都是基于vue-cli开发的,但是虽然每个人的需求不一样,但是都需要定制一些东西。 例如,以 postcss 为例,vue-cli 有一个小陷阱。 默认情况下,autoprefixer 只会对通过 vue-loader 引入的样式产生影响。 也就是说,.vue 文件上的 cssautoprefixer 将会生效。 相关问题issues/544、issues/600。解决方法也很简单粗暴
//app.vue
<style lang="scss">
@import './styles/index.scss'; // 全局自定义的css样式
你可以只在 .vue 文件中引入你想要的样式,也可以更改 vue-cli 文件并在 css-loader 之上添加一个 postcss-loader。 解决方案在上面的问题地址中已经给出了。 我们再来说一下postcss配置问题。 新版本的vue-cliwebpack模板默认在inti后面的目录下有一个.postcssrc.js。 vue-loader的postcss默认会读取这个文件中的配置项,所以可以直接在这里更改配置文件。 配置与postcss相同。
//.postcssrc.js
module.exports = {
"plugins": {
// to edit target browsers: use "browserlist" field in package.json
"autoprefixer": {}
}
}
//package.json
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
上面代码中提到,autoprefixer回家去读取package.json下的browserslist的配置文件。
babel-polyfill
该项目暂时没有兼容性要求。 如果有兼容性需求,可以自己使用babel-polyfill。用于Node/Browserify/webpack
npm install --save babel-polyfill //下载依赖
在入口文件中引入
import 'babel-polyfill';
// 或者
require('babel-polyfill');//es6
将 babel-polyfill 添加到 webpack.config.js 中的条目列表中:
module.exports = {
entry:["babel-polyfill","./app/js"]
}
详情请参考链接
或者更容易暴力使用polyfill.io来使用它提供的CDN地址。 导入这个js后,会手动判断浏览器,加载polyfill不足的部分。 不过国外的速度可能不太好。 您可以自行设置CDN。
跨域问题
楼主vue群里的男同伴问得最多的问题就是关于跨域的,虽然跨域问题确实不是什么难解决的问题。 这里我简单总结一下我推荐的几种跨域解决方案。
开发环境搭建环境
科尔斯
科尔斯
代理人
nginx
这里我只推荐这两种跨域的方法。 其他的跨域方法还有很多,但这两种方法确实是主流。
容易模拟
因为vue-element-admin是一个纯粹的后端个人项目,所以所有数据都是使用mockjs生成的。 它的原理是:拦截所有请求并代理到本地模拟数据,因此网络中不会发出任何请求。 。 但是这不符合实际的业务开发场景,所以本项目使用了不久前刚刚发布的easy-mock。 支持跨域,支持mockjs句型,支持Swagger。 这几点都挺好的。相关文章
基本网址
长期需要线上或者测试环境接口的base_url不一样,或者如果你本地使用easy-mock等模拟数据带到线上环境,想使用自己公司的数据生产环境,可以满足这个要求。 只需使用baseurl即可解决。 首先,我们在 config/ 下有两个配置文件,dev.env.js 和 prod.env.js。 用它来区分不同环境的配置参数。
//dev.env.js
module.exports = {
NODE_ENV: '"development"',
BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',
}
//prod.env.js
module.exports = {
NODE_ENV: '"production"',
BASE_API: '"https://prod-xxx"',
}
同时本项目封装了axios拦截器,方便大家使用。 也可以根据自己的业务进行更改。
import axios from 'axios';
import { Message } from 'element-ui';
import store from '../store';
// 创建axios实例
const service = axios.create({
baseURL: process.env.BASE_API, // api的base_url 读取config配置文件
timeout: 5000 // 请求超时时间
});
// request拦截器
service.interceptors.request.use(config => {
if (store.getters.token) {
config.headers['X-Token'] = store.getters.token; // 让每个请求携带自定义token 请根据实际情况自行修改
}
return config;
}, error => {
// Do something with request error
console.log(error); // for debug
Promise.reject(error);
})
// respone拦截器
service.interceptors.response.use(
response => {
/**
* code为非20000是抛错 可结合自己业务进行修改
*/
const res = response.data;
if (res.code !== 20000) {
Message({
message: res.data,
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都是一个实例,而你的请求都是基于这个实例,所以配置的参数属性都是继承的。
//api.xxx.js
import fetch from '@/utils/fetch';
export function getInfo(token) {
return fetch({
url: '/user/info',
method: 'get',
params: { token }
});
}
//你可以直接这样使用,之前拦截器写的东西都是生效的,
//它自动会有一个你之前配置的baseURL,
//但你说我这个请求baseURL和其它的不同,
//这也是很方便的,你可以字请求内部修改,
//它会自动覆盖你在创建实例时候写的参数如
export function getInfo(token) {
return fetch({
baseURL: https://api2-xxxx.com
url: '/user/info',
method: 'get',
params: { token }
});
}
总结
本文主要介绍vueAdmin是做什么的。 希望大家如果有新的后端项目需要开发,建议基于 vueAdmin-template 进行开发,而 vue-element-admin 更多的是作为集成解决方案使用。 只需找到您需要的功能并使用它们即可。 由于两者的基本架构相同,因此复用成本也很低。
占个坑
常见的陷阱,这里有一个手把手指南,指导您使用 Vue 完成后端系统
项目地址:vueAdmin-template
相关项目地址:vue-element-admin
系列文章一:
手把手教你如何使用vue玩转后端系列1(基础篇)
系列文章二:
手把手教你用vue玩转后端系列2(登录权限)
系列文章三:
手把手教你用vue玩转后端系列3(实战篇)
下一篇文章将真正讲述如何使用Electron来包装现有项目并快速实现跨平台的终端后端。
针对广大需求,特建立QQ群591724180,方便您交流。
尖端
长按二维码加入SF“2017华为开发者大赛交流群”了解更多详情,与你的男同伴组队参与。