Vue项目 成员管理系统 Axios封装和跨域问题 (2)
一、Axios封装1.1 封装Axios对象因为项目中很多组件中要通过 Axios 发送异步请求,来请求一些数据1.2 测试封装的Axios在public下创建db.json数据文件,内容如下:[{ "name": "8080", "age": "10" }]二、跨域问题2.1 什么是跨域前后端分离时,前端和后端API服务器可能不在同一台主机上,就存在跨域问题,浏览器默认会限制跨域访问同源策略:是
一、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翻墙,真正能访问的是代理)
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端口下的数据文件,并渲染到页面上
更多推荐
所有评论(0)