vue项目总结(3)vuex+vue-router+axios实现登陆-权限拦截

上一篇中具体的说了vue-router的一些内容;今天加上axios实现接口上的控制;接着肯定涉及到状态的管理方面的内容了;

还是先说一下涉及到的一些基础内容吧;

了解一下axios

在了解axios的时候;先简单的说一下咱们常用的ajax;我之前更新过关于ajax-API的一些属性讲解的文章;大家可以看一下;其实底层都是对XHR的封装;[https://www.jianshu.com/p/4522b2a120cf];这个文章是基于JQ的ajax的一些属性的讲解;

  • axios与ajax的一些对比;
    首先大家都了解ajax是对XHR的封装;axios;在客户端的使用的时候也是样的;但是axios又对了些api;axios的官方说的和清楚;关于它的优点:


    4364838-02922c4cd518d11a.png
    image.png

    1.浏览器中使用是XMLHttpRequest;但是在node.js中也可以使用和服务端同样的写法;毫无违和感;基础写法都是

const axios = require('axios');

// Make a request for a user with a given ID
axios.get('/user?ID=12345')
  .then(function (response) {
    // handle success
    console.log(response);
  })
  .catch(function (error) {
    // handle error
    console.log(error);
  })
  .then(function () {
    // always executed
  });

// Optionally the request above could also be done as
axios.get('/user', {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  })
  .then(function () {
    // always executed
  });  

// Want to use async/await? Add the `async` keyword to your outer function/method.
async function getUser() {
  try {
    const response = await axios.get('/user?ID=12345');
    console.log(response);
  } catch (error) {
    console.error(error);
  }
}

大家都看到了then;是的;有人这么评价;axios是对ajax使用Promise方法的封装;事实上不是这样的;关于Features中的第三条也提到了支持Promise;
2.关于接下来的一条就是实现拦截使用的功能;Intercept request and response;拦截请求和响应;数据的请求和响应;进行统一拦截;就可以实现权限的控制;
3.剩余的几个功能点都是对功能的加强;修改请求数据和响应数据的格式取消请求;自动处理JSON数据;在客户端支持避免XSRF攻击;大家可以简单了解一下XSRF;最有效的预防方式就是一次有效token;和cookie的key处理;

vue中使用axios;

说过axios的一些功能;开始使用把;
首先安装把;
npm i -D axios;
然后再main.js中引入;因为接下来要做很多请求拦截和逻辑处理;所以就不要在main.js中处理这些了;

4364838-5b9d0e5fcbd9effa.png
image.png

我构建了一个host文件;接下来一一介绍;
首先http.js的内容

/**
 * 接口权限
 * http配置
 */

import axios from 'axios'
import store from '../store/store'
import * as types from '../store/types'
import router from '../router'
import Vue from 'vue';
const Busvue=new Vue();
// axios 配置
// axios.defaults.timeout = 5000;
// axios.defaults.baseURL = 'https://api.github.com';
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
// http request 拦截器

axios.interceptors.request.use(
    config => {
        if (store.state.token) {
            config.headers.common['token'] = store.state.token;
            config.headers.common['Cache-Control'] = 'no-cache';
            config.headers.Pragma = 'no-cache';
        };
        
        //尝试拦截请求内容;
        // var urlStr = config.url;
        // console.log(urlStr.substring(7))
        // if (urlStr.includes('/testca')){
        //     var a = urlStr.substring(7)
            
        //     config.url = '/testca/api'+a;
        // }
        // console.log('获取请求实体的内容',config)
        
        return config;
    },
    err => {
        return Promise.reject(err);
    });

// http response 拦截器
axios.interceptors.response.use(
    response => {
        if (typeof response.data.code!="undefined"&&response.data.code==10104023){
            Busvue.$message({
                message: '无效的token!请重新登陆!',
                type: 'error'
            });
            store.commit(types.LOGOUT);
            router.replace({
                path: '/login',
                query: { redirect: router.currentRoute.fullPath }
            });
        }else{
            return response;
        }
    },
    error => {
        if (error.response) {
            switch (error.response.status) {
                case 401:
                    // 401 清除token信息并跳转到登录页面
                    store.commit(types.LOGOUT);
                    router.replace({
                        path: '/login',
                        query: {redirect: router.currentRoute.fullPath}
                    });
                    break;
                case 403:
                    Busvue.$message({
                        message: '您没有该功能使用权限。',
                        type: 'error'
                    });
                    break;
                case 504:
                    Busvue.$message({
                        message: '网络超时,请重试',
                        type: 'error'
                    });
                    break;
                 
            }
        }else{
            
            store.commit(types.LOGOUT);
            router.replace({
                path: '/login',
                query: { redirect: router.currentRoute.fullPath }
            });
        }
        // console.log(JSON.stringify(error));//console : Error: Request failed with status code 402
        console.log("axios", error);
        return Promise.reject(error.response.data);
    });

export default axios;

一些状态码肯定要和服务端协商好的;比如;401未登录或登陆过期进入到登陆界面;403无权限;接着做无权限的处理;另外中间vuex进行状态管理;先不说;
apiConfig.js;我们将接口进行了统一的处理;大家也可以使用定义各个modules;然后import;就变成这样的文件处理了;


4364838-e5a512b08bdde7b7.png
image.png

里面多的listapi.js以及detail.js都是各个页面的view视图层用到的接口;建议大家放在某个文件里面;我是为了让大家看就不细致的搞了
listApi.js

let baseUrl = '/finance';
let baseUrl2='/testca'
module.exports = {
    //运营后台2.1版本接口管理;
    testapi: [baseUrl+'/customer/admittance/siteCustomers', 'POST'],//获取仓库;
    nodeList: [baseUrl2+'/cloudwarehouse/callboard/list','GET']
};



apiConfig.js

let baseUrl = '/finance';
let baseUrl2='/testca'
import listapi from './listapi'
import detailapi from './detail'
let APIS = {};
Object.assign(API,listapi,detailapi)
console.log(APIS)
const getConfig = apiName => APIS[apiName];
export default getConfig;

也是模块化思想吧;
接下来是axiosAjax.js就是方法的暴露吧

import Vue from 'vue';
import getConfig from './apiConfig.js';
const Busvue = new Vue();
//获取数据GET
let getDataaxios=(url, data)=>{
    return new Promise((resolve, reject) => {
    Busvue.axios({
        method: 'GET',
        url: url + "?t=" + Date.now(),
        headers: {"appCode": "927f951e5e127ea1fb2582695ec7ddff" },
        params: data
    })
    .then(function (res) {
        //接口请求回调
        resolve(res);
    })
    .catch(function (error) {
        //接口异常
       reject(error);
        // console.log("接口异常", error);
    })
  });
};
//获取数据POST
let postDataaxios=(url, data,method)=>{
    return new Promise((resolve, reject) => {
    Busvue.axios({
        method: method.toLowerCase(),
        url: url + "?t=" + Date.now(),
        headers: { "appCode": "927f951e5e127ea1fb2582695ec7ddff" },
        data: data
    })
    .then(function (res) {
        //接口请求回调
       resolve(res);
    })
    .catch(function (error) {
        //接口异常
        reject(error);
        // console.log("接口异常", error);
    })
  });
};
let axiosAjax=(apiKey,data,fun)=>{
    if (getConfig(apiKey)[1].toLowerCase()=='post'||getConfig(apiKey)[1].toLowerCase()=='put'||getConfig(apiKey)[1].toLowerCase()=='delete'){
        return postDataaxios(getConfig(apiKey)[0],data,getConfig(apiKey)[1])
    }else if(getConfig(apiKey)[1].toLowerCase() == 'get'){
        return getDataaxios(getConfig(apiKey)[0],data)
    }else{
        throw new Error('请输入正确的请求方式!现仅支持GET||POST');  
    }
};
export default axiosAjax;

/*
var datas={};参数;回调函数;
this.axiosAjax('testapi', datas, this.testHH)
*

*/

最后一步就是在main.js引入axiosAjax.js;然后axios内容就结束了
main.js

import axiosAjax from './host/axiosAjax.js'
Vue.prototype.axiosAjax = axiosAjax;//封装公用API;
具体在各个模块中的使用方式

this.axiosAjax([接口对应的属性名称]).then((res)=>{
//如果使用listApi的第一个接口  在对应的 [接口对应的属性名称]写上testApi;
返回结果;
})
axios结束了

接下来就是关于vue-router的内容了;在axios对权限实现拦截后;vue-router就要对登陆就行拦截了;

router.js

const libraryAd = resolve => require(["@/components/goodsSearch/goodsSearch"],resolve);


const routes = [
{
        path: '/libraryAd',
        name: 'libraryAd',
        meta: {
            requireAuth: true,
        },
        component: libraryAd
    }];
Vue.use(VueRouter);
// 页面刷新时,重新赋值token;
我们放在sessionStorage中的原因就是要在用户打开新标签页的时候不在新的登陆状态
if (window.sessionStorage.getItem('token')) {
    store.commit(types.LOGIN, window.sessionStorage.getItem('token'));
}

const router = new VueRouter({
    mode: 'history',
    routes
});

router.beforeEach((to, from, next) => {
    sessionStorage.fromRouterpath = from.path;
    sessionStorage.toRouterpath = to.name;

    if (to.matched.some(r => r.meta.requireAuth)) {
        if (store.state.token == "undefined" || store.state.token == null) {
            next({
                path: '/cloudHouse/login',
                query: { redirect: to.fullPath }
            });
            return;
        }
      
    } else {
        next();
    }
   
})

export default router;

今天先到这吧;多学习吧;停不下来的;

猜你喜欢

转载自blog.csdn.net/weixin_34370347/article/details/86941686