在使用vue技術棧開發(fā)各類管理系統(tǒng)時,經(jīng)常需要相同的開發(fā)目錄架設。在日常開發(fā)中,整理了一套自己的開發(fā)目錄。主要包括
vuejs、vue-router、vuex、axios等常用類庫。
開發(fā)依賴
"vuex": "^3.1.0",
"babel-polyfill": "^6.26.0",
"element-ui": "^2.9.1",
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"axios": "^0.18.0",
Git倉庫地址
開發(fā)目錄
vue-template主要使用axios做請求處理,在src/api/index.js中對axios做了二次封裝,然后把封裝函數(shù)gl_ajax掛載在全局vue.prototype上,通過各層嵌套組件通過原型可以獲取gl_ajax函數(shù)。在router/index.js主要是路由定義和路由導航守衛(wèi)功能。詳細情況可以參考提供源碼地址。
|-- App.vue(掛載根組件)
|-- api(封裝請求相關模塊)
| |-- api.js(公用api接口定義)
| |-- config.js(項目請求地址和其他參數(shù))
| |-- index.js(axios二次封裝定義)
|-- components(公用業(yè)務組件)
|-- main.js(程序執(zhí)行入口)
|-- plugins(開發(fā)vue插件目錄)
| |-- el_icon(Icon組件)
| | |-- Icon.vue
| | |-- assets
| | | |-- error.svg
| | | |-- info.svg
| | | |-- success.svg
| | | |-- warning.svg
| | |-- index.js
| |-- el_message(message提示組件)
| |-- index.js
| |-- main.js
| |-- message.vue
|-- router(路由定義和路由守衛(wèi))
| |-- index.js
|-- store(vuex定義和action)
| |-- index.js
| |-- types.js
|-- views(業(yè)務組件)
|-- Home.vue
|-- Login.vue
|-- index.vue
main入口
main入口對類庫進行掛載,二次封裝的函數(shù)gl_ajax、第三方組件庫elementui。vue官方提議對掛載在vue原型鏈上的自定義函數(shù)加前綴$區(qū)分,這里使用alias:$gl_ajax來進行掛載。
import Vue from "vue";
import "babel-polyfill";
import App from "./App";
import router from "./router";
import store from "./store/index.js";
import { gl_ajax } from "./api/index.js";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
Vue.prototype.$gl_ajax = gl_ajax;
Vue.config.productionTip = false;
Vue.use(ElementUI);
new Vue({
el: "#app",
store,
router,
components: { App },
template: "<App/>"
});
路由定義和路由守衛(wèi)
開發(fā)后臺管理系統(tǒng),某些頁面需要對用戶或游客進行權限驗證。所以在路由文件添加路由守衛(wèi),阻止未登錄用戶對需權限的頁面的操作。
在使用vue中采取前后端分離的形式,通過JWT獲取對api接口的請求權限token,在登錄中獲取token,然后保存在sessionStorage中,之所以不把token保存在vuex中,是因為瀏覽器刷新會導致store數(shù)據(jù)重置。失去登錄token。這里采用的是sessionStorage加vuex的形式,避免了上述的弊端。
// 頁面刷新時,重新賦值token
if (window.sessionStorage.getItem("token")) {
store.commit(types.LOGIN, window.sessionStorage.getItem("token"));
}
下面是router/index.js的完整定義源碼
import Vue from "vue";
import VueRouter from "vue-router";
import store from "../store/index";
import * as types from "../store/types";
Vue.use(VueRouter);
const routes = [{
path: '',
redirect: '/login'
}, {
path: "/",
component: resolve => require(["@/views/Home"], resolve),
children: [{
path: '/admin',
name: 'admin',
component: resolve => require(["@/views/index"], resolve)
}]
},
{
path: "/login",
name: "Login",
component: resolve => require(["@/views/Login"], resolve)
}
];
// 頁面刷新時,重新賦值token
if (window.sessionStorage.getItem("token")) {
store.commit(types.LOGIN, window.sessionStorage.getItem("token"));
}
const router = new VueRouter({
mode: "history",
routes
});
//路由導航守衛(wèi)
router.beforeEach((to, from, next) => {
if (to.path == "/login") {
store.commit(types.LOGOUT);
next();
} else {
const token = sessionStorage.getItem("token");
if (!token) {
next({
path: "/login",
query: {
redirect: to.fullPath
}
});
} else {
next();
}
}
});
export default router;
全局數(shù)據(jù)儲存vuex
在路由導航中,使用store加sessionStorage形式保存登錄token,在store/index.js中也定義了登錄和退出操作mutations。
把退出操作定義在store中,是為了下面對登錄權限過期,返回401狀態(tài)碼,進行重定向操作功能。
import Vue from "vue";
import Vuex from "vuex";
import * as types from "./types";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
token: null
},
mutations: {
[types.LOGOUT]: (state, data) => {
sessionStorage.removeItem("token");
state.token = null;
},
[types.LOGIN]: (state, data) => {
sessionStorage.setItem("token", data);
state.token = data;
}
},
actions: {},
getters: {}
});
axios封裝
api/index.js文件中對axios進行了二次封裝。同一根目錄下config.js定義請求超時時間、開發(fā)和線上請求URL。
axios請求攔截
對axios請求錯誤攔截是重點部分。主要對權限過期401和請求超時操作store對保存的token清除,然后再對路由進行重定向。
axios.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
store.commit(types.LOGOUT);
router.replace({
path: "/login",
query: {
redirect: router.currentRoute.path
}
});
}
const message = error.response.data.message ?:'未知錯誤';
Message.error(message);
} else if (error.code == 'ECONNABORTED' && error.message.indexOf('timeout') != -1) {
Message.error("請求已超時");
}
return Promise.reject(error);
}
);
gl_ajax請求封裝
responseType是axios請求文件下載需要的接受類型,文件是通過application/json方式進行獲取。
export const gl_ajax = params => {
return axios({
method: params.method.toLowerCase(),
url: `${axios.defaults.baseURL}${params.url}`,
data: params.method != "get" ? params.data : "",
params: params.method == "get" ? params.data : "",
responseType: params.file ? "blob" : ""
})
.then(res => {
params.success && params.success(res);
})
.catch(err => {
params.error && params.error(err);
});
};
gl_ajax使用
在vue的原型上定義了$gl_ajax函數(shù),在login常見登錄中需要請求接口獲取token權限,下面對$gl_ajax介紹使用方式和對token保存操作。
self.$store.commit(types.LOGIN,token)在vuex中保存token,會在sessionStorage和store分別保存一份token值。防止瀏覽器刷新造成vuex中token丟失。
<template>
<div>
<button @click='loginSystem'>login</button>
</div>
</template>
<script>
import * as types from "../store/types.js";
export default {
name: "Login",
data() {
return {};
},
methods: {
loginSystem() {
const self = this;
this.$gl_ajax({
url: "/login",
method: "post",
data: { ...self.loginData },
success(res) {
if (res.data.status == "ok") {
const token = res.data.jwt;
self.$store.commit(types.LOGIN, token);
self.message("login success");
self.$router.push({
path: "/admin"
});
}
},
error(err) {}
});
}
}
};
</script>
<style>
</style>
如果覺得有幫助,可以給個贊或star呀
github地址:vue-template