一、Axios封装

1.1 封装Axios对象

因为项目中很多组件中要通过 Axios 发送异步请求,来请求一些数据,所以对Axios进行自主封装,在其他文件读取数据的时候,可以一样使用Axios来拿到相应的数据,但是需要对Axios发送AJAX请求时进行拦截,拦截之后去判断请求(比如是拿取数据的请求,或者登录注册的请求),进行一些分类

在 src 目录下创建 utils 目录及 utils 下面创建 request.js 文件

参考:

GitHub - axios/axios: Promise based HTTP client for the browser and node.js

import axios from "axios";//引入axios

const request = axios.create({//?创建一个axios对象,在对象里对axios的请求进行相关的配置
    baseURL: '/',//?决定了你最终发送的请求是什么 baseURL里的内容会拼在你的端口号后边
    //? 根据不同环境设置baseURL,最终发送请求时URL为: baseURL+发送请求时的URL
    timeout: 5000,//请求超时
})

export default request;//将axios作为默认的成员对象导出

对axios进行改写,通过axios.create的方式去创建axios对象,之后将axios作为一个对象进行反出,在其他调用它的地方去写一个方法,通过axios去读数据,再去调用相应的方法再去读文件

之所以封装和改写,是为了在axios中添加拦截器(直接使用axios.get或者axios.post是没有办法添加拦截器的)

1.2 测试封装的Axios

1.2.1 在public下创建db.json数据文件,内容如下:

[{ "name": "8080", "age": "10" }]//需要严格使用双引号 ""

测试1: 

1.2.2 在 src 目录下创建 api 目录及 api 下面创建 test.js 文件

//!测试文件,写相应方法去请求文件,之后输出
import request from "@/utils/request";//@代表 /src

//* 直接调用get,后边加路径,去访问相应的数据文件
request.get('/db.json').then(response => {//public下的文件可以直接读
    console.log('get1', response.data);
}).catch(error => {
    console.log(error.message);
})

1.2.3 在 HelloWorld.vue 中 import 导入 test.js 

import testApi from "@/api/test"; //引入test.js 

执行test.js里所有的内容,用testApi去接返回来的东西 

浏览器控制台,输出数据:

测试2:

1.2.4 采用 config 配置参数发送请求,api\test.js 新增如下代码:

//* 对request进行对象的配置,然后去访问数据文件
request({
    url: '/db.json',
    method: 'get',
}).then((response) => {
    console.log('get2', response.data);
}).catch(error => {
    console.log('error',error.message);
})

浏览器控制台,输出数据:

当前响应的数据只是在test.js中打印而已,但是应该将数据响应到对应的组件当中进行渲染,也就是HelloWorld.vue

测试3:

1.2.5 导出对象方式, api\test.js 新增如下代码:

export default {//?导出默认成员,默认成员是个对象,对象里写了getList方法
    getList() {
        const req = request({
            url: '/db.json',
            method: 'get',
        })

        return req;//req就是配置好相关内容的axios对象
    }
}

1.2.6 在 HelloWorld.vue 中导入 test.js

import testApi from "@/api/test"; //引入test.js 就会执行我test.js里所有的内容 用testApi去接返回来的东西
export default {
    name: "HelloWorld",
    data() {
        return {
            //返回一个数组
            list: [],
        };
    },
    created() { //钩子函数中进行对fechData方法的调用
        this.fechData();
    },
    methods: {
        fechData() {
            //获取数据
            testApi.getList().then((response) => {
                    console.log('get3', response.data);
                    //testApi.getList()这个方法返回的就是配置好的对象,所以可以直接调用.then去拿数据
                    this.list = response.data; //进行赋值
                }).catch((error) => {
                    console.log(error.message);
                });
        },
    },
    props: {
        msg: String,
    },
};

浏览器控制台,输出数据:

在页面上渲染出data返回的数组:

<h1>{{ list }}</h1>// vue语法规则,双大括号加变量名

 渲染出的页面:

 1.3 配置拦截器

在 utils/request 中新增如下代码:

//* 请求拦截器
request.interceptors.request.use(config => {
    // 请求拦截
    return config
}, error => {
    // 出现异常,抛出错误对象
    return Promise.reject(error);
})

//* 响应拦截器
request.interceptors.response.use(response => {
    // response.data
    return response
}, error => {
    return Promise.reject(error);
})

参考: axios/axios: Promise based HTTP client for the browser and node.js (github.com)

二、跨域问题

2.1 什么是跨域

前后端分离时,前端和后端API服务器可能不在同一台主机上,就存在跨域问题,浏览器默认会限制跨域访问

同源策略:是指协议,域名,端口都要相同,其中有任何一个不同都会产生跨域

如下面示例存在跨域:

前端页面部署在:http://localhost:8888 即本地ip端口8888上;

​后端API部署在: http://localhost:8080 即本地ip端口8080上;

虽然协议(http)是一样的,域名(localhost)是一样的,但是端口不一样,所以存在跨域问题

跨域解决: 通过代理请求的方式解决,将 API 请求通过代理服务器请求到 API 服务器,开发环境中,在 vue.config.js 文件中使用 devServer.proxy 选项进行代理配置

将请求发送到代理上去,之后再用代理去访问相应要访问的目标地址,拿到相应数据进行相应的时候,也是从目标地址把内容相应到代理里来,再从代理里把数据响应会代理请求的前端里面去,通过这样的方式去解决跨域(类似于VPN翻墙,真正能访问的是代理)

参考:配置参考 | Vue CLI

2.2 产生跨域

从8080端口号下的服务里把数据读取出来,渲染到端口号为8888的页面里面,直接去读取,会产生跨域问题,不符合浏览器同源规则

2.2.1 将msm文件夹复制保存为msm-demo,更改msm-demo中的vue.config.js,更改端口号

module.exports = {
    devServer: {
        port: 8080,//端口改为8080
        host: 'localhost',
        https: false,
        open: true,
    },
    lintOnSave: false,
    productionSourceMap: false,
}

2.2.2 将msm中的test.js中的url更改

export default {
    getList() {
        const req = request({
            url: 'http://localhost:8080/db.json',//更改路径
            method: 'get',
        })

        return req;
    }
}

2.2.3 更改public/db.json

[{ "name": "8080", "age": 10 }]//便于区分端口

用端口号8888直接去访问端口号8080的数据文件,产生跨域,无法渲染数据

控制台报跨域的错误:

 2.3 解决开发环境跨域问题(加入代理proxy)

 2.3.1 将src目录下utils/request.js 中的 baseURL 修改如下:

baseURL: '/dev-api'//添加标识

2.3.2  在 vue.config.js 文件中使用 devServer.proxy 选项进行代理配置

 proxy: {//?解决跨域问题(不符合浏览器同源规则),代理配置
            '/dev-api': {
                target: 'http://localhost:8080',//进行域名替换 访问目标服务器
                changeOrigin: true,//开启代理,会创建虚拟服务器,接受发送相应请求来请求数据
                pathRewrite: {//对路径进行重写
                    '^/dev-api': ''
                    //表示如果我的url有dev-api就把它替换成一个空串
                    //? 如 /dev-api/db.json 代理为 http://localhost:8080/db.json
                    //拼串的方式 重构代理
                }
            }
        }

 将'dev-api'变为空串的目的:

在封装axios的时候,在baseURL后边加了 '/dev-api' ,所以在发送请求的时候,会把 '/dev-api' 也加在它的请求里面。在配置代理的时候,请求先发送到代理上,代理就相当于一个虚拟的服务器,代理会判断带着 '/dev-api' 请求的真正目的是去访问 'http://localhost:8080' 而不是本地8888的端口,代理会在这里进行相应的替换,将判断的标志替换成空串,因为真正端口下的  /db.json 没有 '/dev-api' 

2.3.3 重新对test.js中get方法的路径进行重新配置

export default {
    getList() {
        const req = request({
            url: '/db.json',//更改路径
            method: 'get',
        })

        return req;
    }
}

解决跨域问题,在8888端口下访问8080端口下的数据文件,并渲染到页面上

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐