框架:vue
路由管理: vue-router
状态管理:vuex
UI库:vue-ant-design
http库: axios
权限验证:
通信凭证: token
前端路由校验: 白名单加meta元信息,路由守卫
插件:
富文本编辑器:vue-quill-editor
图片懒加载: vue-lazyload
省市区:area-data + vue-area-linkage
进度加载:nprogress
...
数据模拟: mockjs
代码规范: eslint
协作工具: git
main.js
引入文件及样式,全局引用或按需引入
vue-ant-design按需引入
import 'ant-design-vue/dist/antd.css';
import {BackTop,}from 'ant-design-vue';
Vue.use(BackTop);
插件引入参照各官方文档,舒心简单
http.js
主要设置axios的拦截以及生产模式和开发模式的api地址
import axios from 'axios';
import { message } from 'ant-design-vue';
import store from './store/store';
// axios.defaults.headers.post['Content-Type'] = 'multipart/form-data'; // 配置请求头
if (process.env.NODE_ENV === 'production') {
// 生产环境,线上环境
axios.defaults.baseURL = 'http://production.test.ink';
} else if (process.env.NODE_ENV === 'test') {
// 测试环境
axios.defaults.baseURL = '';
} else if (process.env.NODE_ENV === 'development') {
// 开发环境
axios.defaults.baseURL = 'http://development.test.ink';
}
// let hide = function() {};
// function startLoading() {
// hide = message.loading('', 0);
// }
// function endLoading() {
// hide();
// }
axios.interceptors.request.use(
// 发送请求前拦截请求,将Token加入到headers.Authorization
config => {
// startLoading();
if (store.getters['USER/USER_TOKEN']) {
// 登录后设置请求头
config.headers.Authorization = store.getters['USER/USER_TOKEN'];
}
return config;
},
error => {
// endLoading();
message.error(`${error.response.statusText},${error.response.status}`);
return Promise.reject(error);
}
);
axios.interceptors.response.use(
response => {
// 返回拦截
// endLoading();
if (response.data.status === '-1') {
// 后台返回-1仅表示token错误
message.error('登录凭证失效或错误,请重新登录!');
}
return response;
},
error => {
switch (error.response.status) {
case 422:
if (error.response.data.errors) {
message.error(
Object.values(error.response.data.errors)[0].toString()
);
} else if (error.response.data.message) {
message.error(error.response.data.message);
}
break;
case 400:
message.error('没有权限');
break;
default:
break;
}
return Promise.reject(error); // 在App.vue全局拦截该错误
}
);
export default axios;
router.js
主要设置白名单及router.beforeEach(),有权限则进入,否则导向403页面,或者页面并无的话404
这里的一些权限信息要跟后台配合好
以及懒加载路由配合Magic Comments使用
登陆后给的token包含了该用户的能够访问的所有前端页面且包含了访问某接口的权限,即使拿到后台接口地址,若没有包含访问该接口的权限,则拿不到数据。如果只做前端的路由权限验证,犹如纸糊,真正的权限验证还是要根据权限访问接口拿到后台的数据
在其他文件使用路由文件的配置this.$router.options.routes,根据this.$router.options.routes和后台传过来的用户能够访问的页面来渲染页面。
components
自己封装的常用组件,文件上传,文件下载...
store.js
模块化
import Vue from 'vue';
import Vuex from 'vuex';
import USER from './modules/user';
import SETTING from './modules/setting';
Vue.use(Vuex);
export default new Vuex.Store({
strict: true,
modules: {
USER,
SETTING,
},
});
mockjs
前期后台接口没有搭建好时,可以使用mockjs模拟临时数据
filter_utils.js
全局过滤器,感觉组件内部的过滤器差不多够用,定义全局也还好
import Vue from 'vue';
Vue.filter('enTozh', function formatDate(value) {})
App.vue
刷新时的状态保存以及捕捉错误,那么只需要写then() ,catch()就可以省略了
created: function() {
// 在页面加载时读取sessionStorage里的状态信息
if (sessionStorage.getItem('store')) {
this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem('store'))));
}
// 在页面刷新时将vuex里的信息保存到sessionStorage里
window.addEventListener('beforeunload', () => {
sessionStorage.setItem('store', JSON.stringify(this.$store.state));
});
window.addEventListener('unhandledrejection', event => {
// 可以在这里添加一些代码,以便检查event.promise 中的 promise 和event.reason 中的 rejection 原因
console.log(`status:${event.reason.request.status},statusText:${event.reason.request.statusText}`);
event.preventDefault();
}, false);
},
eslint
有着eslint的规范约束,现在有自己的代码风格了,并且多人协同时代码风格如果不一样简直不堪入目,eslint能让代码风格统一,看起来就是同一个人写的,舒心。