Vue后臺管理系統(tǒng)用戶認證封裝

在使用vue技術棧開發(fā)各類管理系統(tǒng)時,經(jīng)常需要相同的開發(fā)目錄架設。在日常開發(fā)中,整理了一套自己的開發(fā)目錄。主要包括vuejs、vue-routervuexaxios等常用類庫。

開發(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倉庫地址

vue-template

開發(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。這里采用的是sessionStoragevuex的形式,避免了上述的弊端。

// 頁面刷新時,重新賦值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

在路由導航中,使用storesessionStorage形式保存登錄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請求封裝

responseTypeaxios請求文件下載需要的接受類型,文件是通過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,會在sessionStoragestore分別保存一份token值。防止瀏覽器刷新造成vuextoken丟失。

<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

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容