vue封装axios,路由拦截,cookie封装

1 篇文章 0 订阅

在写项目的时候,我们经常因为一堆乱糟糟的代码而烦心,所以很多时候我们需要把代码封装起来,这样看起来简单有条理,而且方便使用。下面是我对vue项目中,axios请求的封装以及路由拦截,希望能帮助到你。

1.Axios的封装

1.安装axios

npm install axios // 安装axios

2.引入
一般我会在src文件下建一个utils文件夹,里面建一个request.js文件,request.js用来封装我们的axios
注意错误返回的code或者其他错误编码,要根据自己具体后台返回的写,下面的编码只能作为参考

//request.js
import axios from 'axios'; // 引入axios
import qs from 'qs'; //引入qs模块,用来序列化post类型的数据,后面会提到
// 先导入vuex,因为我们要使用到里面的状态对象
// vuex的路径根据自己的路径去写
import store from '@/store/index';
// 路由文件,下面toLgin方法需要用到
import router from '@/router/index';
//导入封装cookie文件
import { removeCookies } from "../utils/auth";

// 环境的切换
// 项目环境可能有开发环境、测试环境和生产环境。我们通过node的环境变量来匹配我们的默认的接口url前缀。axios.defaults.baseURL可以设置axios的默认请求地址
// if (process.env.NODE_ENV == 'development') {
// 	axios.defaults.baseURL = 'https://www.baidu.com';}
// else if (process.env.NODE_ENV == 'debug') {
// 	axios.defaults.baseURL = 'https://www.ceshi.com';
// }
// else if (process.env.NODE_ENV == 'production') {
// 	axios.defaults.baseURL = 'https://www.production.com';
// }

// create an axios instance
const service = axios.create({
    baseURL: BASE_URL,
    timeout: 30000,// request timeout
    // "Content-Type": "application/x-www-form-urlencoded"
})

// post请求的时候,我们需要加上一个请求头,所以可以在这里进行一个默认的设置,
// 即设置post的请求头为application/x-www-form-urlencoded;charset=UTF-8
// axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';


/**
 * 跳转登录页
 * 携带当前页面路由,以期在登录页面完成登录后返回当前页面
 */
const toLogin = () => {
    router.replace({
        path: '/login',
        query: {
            redirect: router.currentRoute.fullPath
        }
    });
}
/**
 * 请求失败后的错误统一处理
 * @param {Number} status 请求失败的状态码
 */
const errorHandle = (status, other) => {
    // 状态码判断
    switch (status) {
        // 401: 未登录状态,跳转登录页
        case 401:
            toLogin();
            break;
        // 403 token过期
        // 清除token并跳转登录页
        case 666:
            alert('登录过期,请重新登录');
            removeCookies('token');
            removeCookies('user');
            setTimeout(() => {
                toLogin();
            }, 1000);
            break;
        // 404请求不存在
        case 404:
            alert('请求的资源不存在');
            break;
        case status:
            alert(other);
            break;
        default:
            console.log(other);
    }
}

// 添加请求拦截器
service.interceptors.request.use(config => {
    console.log(config);
    // 每次发送请求之前判断vuex中是否存在token
    // 如果存在,则统一在http请求的header都加上token,这样后台根据token判断你的登录情况
    // 即使本地存在token,也有可能token是过期的,所以在响应拦截器中要对返回状态进行判断
    const token = store.state.token;
    token && (config.headers.Authorization = token);
    if(config.method=='post'){
        config.data = qs.stringify(config.data)
    }
    return config;
}, error => {
    console.log(error);
    Promise.error(error);
})

// 添加响应拦截器
service.interceptors.response.use(
    response => {
        console.log(response);

        // 如果返回的状态码代表错误
        if (response.data.errno != 0) {
            // errorHandle(response.data.errno, response.data.errmsg);
            return Promise.reject(response.data);
        } else {
            return Promise.resolve(response.data);
        }
    },
    error => {
        console.log('error');
        if (error.response.status) {
            if (error.response.status != 200) {
                errorHandle(error.response.status, error.response.statusText);
                return Promise.reject(response);
            } else {
                // 处理断网的情况
                // eg:请求超时或断网时,更新state的network状态
                // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
                // 关于断网组件中的刷新重新获取数据,会在断网组件中说明
                // store.commit('changeNetwork', false);
            }
            return Promise.reject(error.response);
        }
    }
)
export default service;

3.配置文件
以上就是request.js的内容
上面我们写的api的base_url,需要在其他文件写一下,因为我现在写的需要进行跨域处理,所以我们先写一下跨域

//    /config/index.js
   // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': { //代理地址
        target: 'https://www.********.com', //需要代理的地址
        changeOrigin: true, //是否跨域
        secure: false,
        pathRewrite: {
          // '^/api': '' //本身的接口地址没有 '/api' 这种通用前缀,所以要rewrite,如果本身有则去掉
        }
      }
    },
//  /build/webpack.dev.conf.js
    new webpack.DefinePlugin({
      'process.env': require('../config/dev.env'),
      'BASE_URL':'"/api"'
    }),

4.封装接口
上面请求已经封装好了,下面我们开始封装接口。封装接口有利于我们管理请求接口。
我们在src下面创建一个api文件夹,文件夹里创建index.js文件,用来封装我们的请求接口。

/api/index.js

import request from '../utils/request'

export function getInfo(params) {
    return request({
        url: '请求接口',
        method: 'get',
        params: params,
        loading: true // loading效果
    })
}

export function login(params) {
    return request({
        url: '请求接口',
        method: 'post',
        data: params,
    })
}

5.使用vuex状态管理
这一步根据需求决定要不要使用,不需要的话直接跳过。
1.安装vuex

npm install vuex

2.在src下面创建 store文件夹,接着创建index.js,引入并使用vuex

import Vue from 'vue'
import Vuex from 'vuex'
import {setCookies} from "../utils/auth";

Vue.use(Vuex)

const store = new Vuex.Store({
    // 全局变量
    state: {
        user: null,
        token: ''  //初始化token
    },
    mutations: {
        //存储token方法
        //设置token等于外部传递进来的值
        setToken(state, token) {
            state.token = token
            setCookies('token',token,1); //同步存储token
        },
        setUser(state, user) {
            state.user = user
            setCookies('user',user,1); //同步存储token
        },
    },
})

export default store

6.缓存 cookie
我们需要使用到缓存来存储一些信息,这里我用的是cookie

1.安装js-cookie
npm install js-cookie

2.引入并使用,在utils文件夹下创建auth.js文件
封装cookie

// auth.js
import Cookies from 'js-cookie'

//获取存取的cookie值
export function getCookies(name) {
  return Cookies.get(name)
}
//获取存取的cookie值(获取的是对象,所以需要进行处理)
export function getJsonCookies(name) {
  return Cookies.getJSON(name)
}
//存取cookie
export function setCookies(name,value,time,path) {
  return Cookies.set(name, value,{ expires: time, path:path })
}
//清除cookie
export function removeCookies(name) {
  return Cookies.remove(name)
}

7.页面调用接口
现在我们创建三个页面模拟一下登录的一些情况
1.index.vue 首页(不需要登录也可以进入)
2.login.vue 登录页面
3.user.vue 用户页面 (需要登录才可以进入否则会被拦截)

首页大概就这这样,有去登录和进入内部user页面两个链接
在这里插入图片描述在这里插入图片描述

//index.vue

<!-- 组件的模板 -->
<template>
  <div class="car">
    <div  v-if="isLogin">
      <img :src="user.avatar" alt="">
      <p>{{user.nickname}}</p>
      <button @click="outLogin">退出登录</button>
    </div>
    <router-link :to="{path:'/login',query:{ redirect:decodeURIComponent('/') }}" tag="button" v-else>去登陆</router-link>
    <router-link to="/user" >进入内部</router-link>
  </div>
</template>

<!-- 组件的模型 -->
<script>
import { getInfo, login } from "../api/index";
import { getCookies,getJsonCookies,removeCookies } from "../utils/auth";
export default {
  data() {
    return {
      isLogin:false,
      user:{},
    };
  },
  methods: {
    // 获取列表
    get() {
      var p = {
        source: "h5",
        host: "1"
      };
      getInfo(p).then(res => {
        console.log(res);
      });
    },
    // 获取用户登录信息
    getInfo(){
      if(getCookies('token')&&getCookies('user')){
        this.isLogin = true;
        console.log(getJsonCookies('user'))
        this.user = getJsonCookies('user');
      }
    },
    // 退出登录
    outLogin(){
      removeCookies('user');
      removeCookies('token');
      window.location.reload();
    },
  },
  mounted() {
    this.getInfo();
  }
};
</script>

<!-- 组件的样式 -->
<style scoped>
</style>

上面我们给一个条件,登录和未登录两种状态,显示的效果是不一样的,未登录显示去登录按钮,登录状态就显示用户信息。
点击去登录会跳到登录页面。
点击进入内部可以跳转到user页面,但是user页面需要登录才能进,所以我写了一个路有拦截,那些需要登录才能进入的页面,我都有进行处理,会在后面提到。点击进入内部跳转按钮,根据我后面写的路由拦截,如果是登录状态,就直接进入,如果未登录,就弹窗提示是否登录,确认进入登录页面,取消留在当前页面。


登录页面

//login.vue

<!-- 组件的模板 -->
<template>
  <div class="car">
    <button @click="onlogin">登录</button>
  </div>
</template>

<!-- 组件的模型 -->
<script>
import { getInfo, login } from "../api/index";
import { getCookies, getJsonCookies, removeCookies } from "../utils/auth";
export default {
  data() {
    return {};
  },
  methods: {
    onlogin() {
      var user = {
        phone: "**************",
        password: "**********",
        source: "pc",
        login_platform: "1",
        type: "3"
      };
      login(user).then(res => {
        var token = res.data.token;
        var userInfo = res.data.userInfo;
        var that = this;
        // 将token存入cookie和vuex
        this.$store.commit("setToken", token);
        this.$store.commit("setUser", userInfo);
        if (that.$route.query.redirect == undefined) {
          that.$router.push("/");
        } else {
          that.$router.push(that.$route.query.redirect);
        }
      });
    }
  },
  mounted() {}
};
</script>

<!-- 组件的样式 -->
<style scoped>
</style>

登录成功直接返回到首页(从哪个页面进去登录页面,就返回到哪个页面)
登录成功后需要将token和用户信息存起来,以便后面继续使用。

8.路由拦截
对于有些未登录不能进入的页面,我们需要写个路由拦截。
在路由文件里进行处理

// /router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import { getCookies } from "@/utils/auth";

Vue.use(Router)

let router=new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'index',
      component: () => import('@/pages/index'),
    },
    {
      path:'/login',
      name:'login',
      component: () => import('@/pages/login'),
    },
    {
      path:'/user',
      name:'user',
      component: () => import('@/pages/user'),
      meta: { requireLogin:true}
    }
  ]
})

//路由拦截
router.beforeEach((to, from, next) => {
  let token = getCookies('token');
  if(to.meta.requireLogin){
    if(token){
      next();
    }else{
      let ifLogin = confirm('是否需要登录?')
      if(ifLogin){
        next({
          path:'/login',
          query:{ redirect:decodeURIComponent(to.fullPath) }
        })
      }else{
        next(false)
      }
    }
  }else{
    next();
  }
  
})

export default router;

以上应该是比较完善的代码了,后续有补充的我会加上去,希望我的笔记能够帮到你们。

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值