Vue 封装axios

发布于:2024-05-22 ⋅ 阅读:(71) ⋅ 点赞:(0)

【一】准备工作

(1)安装必要插件

  • 安装Axios,这是必要的。默认最新版
npm install axios -S
或 
cnpm install axios -S
  • 安装elementui-plus,用于提示信息
npm install element-plus --save
# 或
cnpm install element-plus --save
  • 安装vue-router,用于路由跳转
npm install  vue-router@4 -S
# 或者  
cnpm install  vue-router@4 -S
  • 其他插件,视开发情况自己决定,这是我目前安装的版本

image-20240511191626912

  • 最后在入口文件(main.js)中注册这些插件
import {createApp} from 'vue'
import App from './App.vue'
import router from './router'
import ElementPlus from "element-plus";
import 'element-plus/dist/index.css'

createApp(App).use(ElementPlus).use(router).mount('#app')

(2)后端返回数据格式统一

  • 后端正常返回信息格式
    • 有一个必要的code:标识响应成功与否,这了规定成功是100,失败是其他的
    • 有一个msg:无论成功与否,返回描述信息
    • results或result:
      • 返回多条信息,那么就是results,一个列表套字典(对前端来说是数组套对象)
      • 返回单条信息,那么就是result,一个字典格式(对前端来说是对象)
      • 当然也可以没有这个字段信息
    • 其他信息字段
{
    "code": 100,
    "msg": "信息",
    "results": [
        {
            "id": 1,
            "name": "bruce"
        },
        {
            "id": 2,
            "name": "lucy"
        }
    ]
}

image-20240511193341608

【二】封装axios

(1)分部分讲解

  • 导入模块,指定基础路由
    • axios是肯定要导入的模块
    • router用于路由跳转
    • ElMessage用于信息提示
import axios from "axios";
import {ElMessage} from 'element-plus'


axios.defaults.baseURL = "http://localhost:8000/"
  • 创建请求对象,指定超时时间,指定编码格式
    • 创建请求对象,叫做request
    • 指定访问超时时间为5s:timeout: 5000
    • 指定请求头中的编码格式:
      • headers: {'Content-Type': "application/json; charset=utf-8"}
const request = axios.create({ 
    timeout: 5000,
    headers: {
        'Content-Type': "application/json; charset=utf-8"
    }
})
  • 请求发出前拦截器
    • 部分信息页面肯定是需要登录才可以查看的,即需要携带token信息
    • 指定请求头携带token信息,
    • 首先从本地会话中获取token,然后拼接指定的格式(这是jwt认证,所以要拼接一下)
request.interceptors.request.use(config => {
    const token = localStorage.getItem("token")
    if (token) {
        config.headers['Authorization'] = "Bearer " + token
    }
    return config
})
  • 请求响应拦截部分

    • 首先后端的返回数据应该是满足一定格式,这个在准备工作中说过了

    • 返回的code如果是100,那么就是成功了,所以正常返回数据信息即可

    • 如果返回code不是100,那么就是失败了

    • 再就是其他错误了,这个都是不正常的返回数据信息格式

request.interceptors.response.use(
    response => {
        let res = response.data
        if (res.code === 100) {
            return response.data
        } else {
            // ElMessage.error(!res.msg ? '请求服务器异常,请联系管理员' : res.msg)
            return Promise.reject(!res.msg ? '请求服务器异常,请联系管理员' : res.msg)
        }
    },
    error => {
        let errorMessage;
        if (error.response && error.response.data.msg) {
            errorMessage = error.response.data.msg
        } else if (error.message) {
            errorMessage = error.message; // 使用axios的默认错误消息
        } else {
            errorMessage = '未知错误'; // 如果以上都不满足,给出默认消息
        }

        ElMessage.error(errorMessage, ); // 显示错误消息
        return Promise.reject(error); // 拒绝这个promise并返回原始错误对象
    }
)

(2)整体代码

  • src目录下创建一个http文件夹,在文件夹内创建一个index.js文件(方便导入)
  • 写入如下代码
import axios from "axios";
import {ElMessage} from 'element-plus'


axios.defaults.baseURL = "http://127.0.0.1:8000/api/v1/"


const request = axios.create({
    timeout: 5000,
    headers: {
        'Content-Type': "application/json; charset=utf-8"
    }
})

request.interceptors.request.use(config => {
    const token = localStorage.getItem("token")
    if (token) {
        config.headers['Authorization'] = "Bearer " + token
    }
    return config
})


request.interceptors.response.use(
    response => {
        let res = response.data
        if (res.code === 100) {
            return response.data
        } else {
            // ElMessage.error(!res.msg ? '请求服务器异常,请联系管理员' : res.msg)
            return Promise.reject(!res.msg ? '请求服务器异常,请联系管理员' : res.msg)
        }
    },
    error => {
        let errorMessage;
        if (error.response && error.response.data.msg) {
            errorMessage = error.response.data.msg
        } else if (error.message) {
            errorMessage = error.message;
        } else {
            errorMessage = '未知错误';
        }

        ElMessage.error(errorMessage);
        return Promise.reject(error);
    }
)

export default request

【三】使用

(1)选项式API风格(很少用)

  • 这种方式是较为少见的,但是还是简单写一下
    • 首先在入口文件(main.js)中,创建一个插件来设置全局的axios的实例
import axios from './http'

const axiosPlugin = {
    install(app, options) {
        app.config.globalProperties.$axios = axios; // 在 Vue 3 中设置全局属性
    }
}

createApp(App).use(ElementPlus).use(axiosPlugin).use(router).mount('#app')

  • 测试代码
    • 随便写一个HomeView.vue
<script>
export default {
  name: "HomeView",
  created() {
    this.testRes()
  },
  methods: {
    testRes() {
      this.$axios({
        method: 'get',
        url: 'user/test_response/'
      }).then((response) => {
        console.log(response)
      })

    },

  }
}
</script>

image-20240512140231775

(2)组合式API风格(推荐)

  • 这个就简单的多
    • 不需要再入口文件(main.js)中创建插件来全局设置
    • 哪里需要在哪里使用即可
    • 同样的在HomeView.vue中测试
<script setup>
import request from "../http/index.js";

request({
  method: "get",
  url: "user/test_response/",
}).then(res => console.log(res))

</script>

image-20240512140653057

  • 测试一下token能否正常携带
    • 在代码中添加一行
      • localStorage.setItem('token','sssss.ssss.sss')
    • 键是token,值无所谓,只是测试而已
<script setup>
import request from "../http/index.js";
localStorage.setItem('token','sssss.ssss.sss')
request({
  method: "get",
  url: "user/test_response/",
}).then(res => console.log(res))

</script>
  • 首先查看LocalStorage中是否添加成功

    • image-20240512141303865
  • 在检查发送的请求中是否携带上了token

    • image-20240512141332499