阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Vue中使用axios原理分析及解决前端跨域问题

61次阅读
没有评论

共计 6453 个字符,预计需要花费 17 分钟才能阅读完成。

Vue 中使用 axios 原理分析及解决前端跨域问题

1. 什么是 Axios?

Axios(ajax i/o system),是 Vue 创建者主推的请求发送方式,因其简单的配置与良好的性能被前端爱好者所喜爱。众所周知,在进行网页设计时经常需要从后端拿数据,在 Web 应用初期会将整个页面或者文档直接拿过来,随着 Web 应用的发展,人们对性能的不断提升,逐渐向无页面刷新从后端获取数据,而 axios 就是其中一种新兴、火热的方式。在学习 Vue 中使用 axios 时,不需要太过于了解请求的发送过程,但需要对各种请求方式有一个大致的认识。本文将会从 0 到 1 的介绍 vue 中如何使用 axios,并结合项目实例加深大家印象。

Vue 中使用 axios 原理分析及解决前端跨域问题

注意:第一部分只是带大家了解一下 axios 是什么以及其如何使用,具体项目中的应用还要看第二三部分。

1.1. axios 概念

axios是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

axios本质上也是对原生 XHR(XMLHttpRequest)的封装,只不过它是 Promise 的实现版本,符合最新的 ES 规范。

新手可能容易弄混 ajax 与 axios 两个概念:

  • Ajax(Asynchronous Javascript And XML)不是一种编程语言,而是一种用于创建更好更快以及交互性更强的 Web 应用程序的技术。这种技术可以用到各种各样的库上。

  • Axios(ajax i/o system)是基于 Ajax 技术实现的一种库,市面上还有许多这样的库例如 JQuery。

Axios通常具有以下特点:

  • 从浏览器创建 XMLHttpRequests

  • 从 node.js 创建 http 请求

  • 支持 Promise API

  • 拦截请求和响应

  • 转换请求和响应数据

  • 取消请求

  • 自动转换 JSON 数据

  • 客户端支持防御 XSRF

  • 主流及大众浏览器宽泛的支持

  • 配置简单、安装简便

1.2. vue 中使用 axios

第一步:安装(安装起来灰常简单按照步骤执行即可)

  • 首先进入你的项目中 src 所在的目录

  • 然后进入 cmd 命令行

  • 执行 npm install axios

  • 即可

第二步:引入项目

import axios from "axios"

第三步:发送请求并获取响应

这里仅仅是发送请求的其中一种方式(调用 api),发送请求方式有两种:

  1. 传入对象发送;

  2. 调用 api 发送。

// 请求 github 接口,根据用户名获取用户头像
axios.get(`https://api.github.com/search/users?q=${this.tempstr}`).then(
  // 响应成功(response 存放了所有的响应信息)
  response=>{
    this.$bus.$emit("getDatas",{"objData":response.data.items,"isLoding":false,"error":""})
  },
  // 出错
  error=>{
    console.log(error.message)
    this.$bus.$emit("getDatas",{"objData":[],"isLoding":false,"error":error.message})
  }
)

1.3. Axios 两种请求方式

本质都是发送了一个 get 请求,一种是调用接口,一种是传入对象。在项目中使用时一般先创建一个 axios 对象对其进行二次封装,并添加请求、响应拦截器。这里只作为了解。

①. 调用接口

this.$axios.get('后端 url',{
      params: {
          id:1
      }
  }).then(res=>{
          console.log(res.data);
      },err=>{
          console.log(err);
  })

②. 传入对象

传入对象常用配置:

参数名 作用
baseURL 请求的域名,基本地址,类型:String
timeout 请求超时时长,单位 ms,类型:Number
url 请求路径,类型:String
method 请求方法,类型:String
headers 设置请求头,类型:Object
params 请求参数,将参数拼接在 URL 上,类型:Object
data 请求参数,将参数放到请求体中,类型:Object

this.$axios({
    method: 'get',
    url: '后端 url',
    params: {
        id:1
    }
}).then(res=>{
    console.log(res.data);
},err=>{
    console.log(err);
})

Vue 中使用 axios 原理分析及解决前端跨域问题Vue 中使用 axios 原理分析及解决前端跨域问题

接下来将会对请求类型进行细化,介绍 axios 支持的请求类型。

1.4.Axios 支持的请求类型

①.get 请求

不带请求参数:

方式一: axios({methods: 'get', url: '/ulr'})
方式二: axios.get('/url')

带请求参数:

方式一: axios.get('/url', {params: {id: 12}})  // 请求的地址实际为 localhost:8080/url?id=12
方式二: axios({
         methods: 'get',
         url: 'url',
         params: {
              id:12
         }
     })

②.post 请求

let data = {}
let config = {}
方式一:  axios.post('/url',data,config)
方式二:  axios({
     methods: 'post',
     url: '/url',
     data: data,
     config: config
})

③.put 请求

该请求和 post 类似,只是请求方法接口不同,传入对象的 methods 不同

④.patch 请求

该请求和 post 类似,只是请求方法接口不同,传入对象的 methods 不同

⑤.delete 请求

axios.delete('/url', {params: {id: 12}})  # 参数在 url params 很重要
axios.delete('/url', {data: {id: 12}}) # 参数在请求体中 将 params 改为 data 就行 

2. 跨域问题解决方案

2.1. 什么是跨域问题?

由于浏览器的同源策略限制,进而产生跨域拦截问题。同源策略是浏览器最核心也最基本的安全功能;所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。这里要着重强调的是跨域问题是因为浏览器的原因,请求响应都是正常的,响应结果也交给了浏览器,只是因为没有进行相应的配置浏览器不将数据拿给用户。

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略在解决浏览器访问安全的同时,也带来了跨域问题,当一个请求 url 的协议、域名、端口三者之间任意一个与当前页面 url 不同即为跨域。

跨域问题通常会抛出类似于下面的错误:

Access to XMLHttpRequest at 'http://43.143.232.114:8080/login' from origin 'http://localhost:8081' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No'Access-Control-Allow-Origin' header is present on the requested resource.

当然这种问题并不是没有解决方案的常见的方法有三种:前端对脚手架文件进行配置、nginx 进行转发、后端写相应的字段配合。彻底解决跨域请求还需要了解一下简单请求与复杂请求的概念,这里主要是教大家在 vue 中使用 axios,就不进行过多的赘述了,后面会专门出一篇文章教大家彻底理解并解决跨域问题。

2.2. 方案一:在 Vue 中进行配置

在前面介绍创建 vue 项目时曾提到过 vue.config.js 配置文件,这个配置文件可以对我们的项目做一些个性化定制,也是我们解决跨域问题的重要途径之一。vue 快速搭建一个项目在上面文章中有对 Vue 基础配置进行介绍。

Vue 中使用 axios 原理分析及解决前端跨域问题

配置文件内容如下:

const {defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave:false, /* 关闭语法检查 */
  // 开启代理服务器(方式一)两个留一个即可
     devServer: {
     proxy: 'http://localhost:5000'
   }, 
    // 开启代理服务器(方式二)
    devServer: {
    proxy: {
       // 第一个跨域代理
      '/server1': {
        target: 'http://localhost:5000',
        // 这样的写法是一种简写,会将原始路由中的 /server1 使用空格替换掉
        pathRewrite:{'^/server1':''},
         ws: true, // 用于支持 websocket
         // 用于控制请求头中的 host 值,这个为 true,会将请求头中的 host 字段变为 target 设置的值
         changeOrigin: true 
      },
      // 第二个跨域代理
      '/server2': {
        target: 'http://localhost:5001',
        pathRewrite:{'^/server2':''},
         ws: true, // 用于支持 websocket
         changeOrigin: true // 用于控制请求头中的 host 值
      }
    }
  }
})

2.3. 方案二:使用 Nginx 转发

使用这种方法需要有 Nginx 的基础知识,由于篇幅有限这里只提供思路,不进行细致的介绍了:

  • 在前端主机安装 Nginx

  • 配置 Nginx 主配置文件进行路由转发

  • 启动 Nginx 服务器

2.4. 方案三:后端配合

这里做的工作就是将响应头字段中的指定字段添加上即可,这里给出 Golang 的跨域请求设置

//resp 是响应对象
resp.Header().Set("Access-Control-Allow-Origin", "*") // 允许访问所有域

3. 封装 Axios 对象

项目中使用 axios 时,并不是直接使用其接口,通常会将其进行封装,对其功能进行定制。

以下实例就是对 axios 原有对象进行定制封装,然后实现自己的接口并调用

3.1. 创建 axios 实例

/**
 * 封装的 axios
 */
import axios from 'axios'
import qs from 'querystring'

/**
 * 错误函数 解析常用的 http 状态码
 * 2xx:成功
 * 3xx: 重定向
 * 4xx: 资源不存在
 * 5xx:服务器错误
 * 
 */
const  ErrorHandle=(status, info) => {
    switch (status) {
        case 400:
            console.log('400- 表示请求报文中存在语法错');
            break;
        case 401:
            console.log('401- 未经许可,需要通过 HTTP 认证');
            break;
        case 403:
            console.log('403- 服务器拒绝该次访问(访问权限出现问题)');
            break;
        case 404:
            console.log('404- 表示服务器上无法找到请求的资源');
            break;
        case 500:
            console.log('500- 表示服务器在执行请求时发生了错误,\
            也有可能是 web 应用存在的 bug 或某些临时的错误时;');
            break;
        case 503:
            console.log('503- 表示服务器暂时处于超负载或正在进行停机维护,无法处理请求');
            break;
        default:
            console.log(info);
            break;
    }
}

// 自定义新建一个 axios 实例
const install = axios.create({
    baseURL:process.env.VUE_APP_BASE_URL,// 网络请求的基础路径,这里是 vue 脚手架运行时开启的端口 
    timeout: 5000,// 请求等待时间 时间到了后台没有返回数据 请求中段
})

3.2. 请求拦截器

以下代码将在请求发送出去之前执行,通常用于对请求中的数据进行指定格式化的转换

// 拦截器 
// 添加请求拦截器
install.interceptors.request.use(function (config) {
    console.log('添加请求拦截器',config);
    // 处理 post 请求发送的参数格式
    if(config.method==='post'){
        config.data = qs.stringify(config.data)//{} 转 xx=xx&xx=xx 
    }
    // 配置请求 token 
    let token= localStorage.getItem('token')
    if(token){
        config.headers.Authorization=token;
    }else{
        return config;
    }
    // console.log('添加请求拦截器 --config',config);
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

3.3. 响应拦截器

以下代码用于响应来到前执行,通常用于检验响应有没有出错

// 添加响应拦截器
install.interceptors.response.use(
    response=>response,
    error=>{
        console.log('响应拦截器错误',error);
        let {response } = error;
        // 对响应错误做点什么
        ErrorHandle(response.status,response.info)
  });

最终将 axios 暴露出去

export default  install;

3.4. 导入定制的 axios 并使用

以下两个文件可以装进一个 api 文件夹下,专门负责网络请求

base.js

const base ={
    host:'http://localhost:8989',// 基础域名
    /*
    ...
    指定接口对应的路由
    */
}

export default base;

index.js

/**
 * 请求的方法
 */
import base from './base'
// 导入二次封装的 axios 文件
import axios from '../utils/request'

//axios 接口配置基础地址
// axios.defaults.baseURL = process.env.VUE_APP_BASE_URL;

const api = {
    // 自己指定接口,例如下面制定的一个接口
    /**
     * 登录接口
     */
    getLogin(params) {//params={username:'',password:''}
        return axios.post(base.login, params)
    },
}

export default api

做完上述工作,就可以直接在我们的项目中引入并使用,想用什么功能的接口自己封装即可(不亦乐乎)。

main.js

import api from './api/index'
Vue.prototype.$api = api;

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-07-03发表,共计6453字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中