在前端项目开发中,一个好的请求封装可以给我们带来诸多便利,减少了代码重复,优化了问题处理等。那接下来我们一起学习一下怎么做到对一个请求的简单封装吧。主要通过对axios请求的二次封装,实现页面的请求以及必要的优化。
一、引入axios
学习第一步,安装加引入。(押韵,哈哈哈)
安装axios
npm install axios
新建utils文件夹下request.js文件用于请求的封装,初始化的封装,后面我们一步步来。
-
import axios
from axios
-
const service=axios.
create({
-
baseURL:
'',
//请求地址
-
timeout:
1000,
//请求超时时间,如果超给改时间会中断
-
// headers: {'X-Custom-Header': 'foobar'}//自定义请求头
-
})
-
//添加请求拦截器
-
service.
interceptors.
request.
use(
(config)=> {
-
// 在发送请求之前做些什么
-
return config;
-
},
(error)=> {
-
// 对请求错误做些什么
-
return
Promise.
reject(error);
-
});
-
-
//添加响应拦截器
-
service.
interceptors.
response.
use(
(response)=> {
-
// 对响应数据做点什么
-
return response;
-
},
(error)=> {
-
// 对响应错误做点什么
-
return
Promise.
reject(error);
-
});
-
-
export
default service
大家会发现url是空的,在开发中这个url一般都是动态的,更加环境去切换的这个地方需要插播一个小知识关于.env文件的使用。
二、关于.env文件的使用
1.模式
在vue-cli中模式是一个重要的概念,默认情况下有三个模式。
对于下面所说的命令,大家可以看一下项目中的package.json文件,一看就明白了

- development 模式用于 vue-cli-service serve
- production 模式用于 vue-cli-service build 和 vue-cli-service test:unit
- test 模式用于 vue-cli-service test:unit
development模式对应我们开发环境对应的命令是 serve命令,也就是说我们启动项目后就在development模式下运行
production模式对应打包命令build。打包后在production模式下运行
你可以通过传递 --mode 选项参数为命令行覆写默认的模式。例如,如果你想要在构建命令中使用开发环境变量:
vue-cli-service build --mode development
总结,可以通过命令动态配置,配置对于模式下对应那些配置。
我们一般通过.env文件进行请求地址的配置,例如存在多个地址的情况,可以通过命令进行灵活配置。
2.process.env环境对象
process.env 是 Node.js 中的一个环境对象。其中保存着系统的环境的变量信息。可使用 Node.js 命令行工具直接进行查看(如下图所示)。

在不同的模式会有不同的环境变量
在 development 模式下 NODE_ENV 的值会被设置为 “development”
在 production模式下 NODE_ENV 的值会被设置为 “production”
3..env文件的执行顺序
.env 无论开发环境还是生产环境都会加载的配置文件
.env.development 开发环境加载的配置文件
.env.production 生产环境加载的配置文件研发环境 加载顺序:.env .env.development 同一个变量名 后者会覆盖前者
生产环境 加载顺序:.env .env.production 同一个变量名 后者会覆盖前者
三、配置开发环境下的请求地址
因为我们现在是在开发模式,所以在.env.development文件中配置我们需要请求的地址(如下)。
对应的ip需要填写服务器ip和对应端口号
# just a flag
NODE_ENV = 'development'# base api
VUE_APP_BASE_API = 'http://10.0.0.165:9588'
然后我们上面的请求url就可以拿到对应的值了
-
const service=axios.
create({
-
baseURL: process.
env.
VUE_APP_BASE_API,
//请求地址
-
timeout:
10000,
//请求超时时间,如果超给改时间会中断
-
// headers: {'X-Custom-Header': 'foobar'}//自定义请求头
-
})
然后我们建立api文件夹进行接口的模块化区分,不同模块对应不同的模块js。

进行一个get请求进行封装是否成功的测试
-
import request
from
"@/utils/request";
-
-
export
function
list(
){
-
return
request({
-
url:
`/api/list`,
-
method:
"get"
-
})
-
}
这是第一集用于测试服务器开发get请求的接口,当时我们测试是成功的。因为测试,所以我们怎么简单怎么来,主要是测试是否成功。
在app.vue页面,进行一个简单的请求
-
<template>
-
<div id="app">
-
<router-view/>
-
</div>
-
</template>
-
-
<script>
-
import {list}
from
'@/api/list'
-
export
default {
-
created(
){
-
list().
then(
res=>{
-
console.
log(res);
-
})
-
}
-
}
-
</script>
-
<style lang="less">
-
-
@import
"@/assets/style/reset.css";
-
</style>
然后重点来了!!!哈哈哈哈,报错了,告诉我跨域了,然后就大结局了,再见了各位。

然而并没有结束,让我们一起解决跨域吧,
前端:后台,跨域了,你解决下
后端:自己解决,前端配置代理不会么?
前端:离职,不干了
现在,我们是后端了,作为一个前端喜欢的后端,我只能说,我来搞,交给我!!!(虽然前后端都是我,呜呜呜)
四、后端通过cors解决跨域
其实对于后端来说,解决跨域很简单,只需要使用CORS就可以了,一共需要两步
第一步:安装cors
yarn add cors
npm install cors
npm和yarn都可以哈,yarn安装快一点,各凭喜好
第二步:使用cors()解决跨域
以下是nodejs服务器端的代码,app.js文件中引入并使用
//引入
const cors = require('cors')
//使用
app.use(cors())
然后再继续请求试一下,发现跨域就这样解决了。

五、关于跨域的相关知识
cors又称跨域资源共享,由一系类HTTP响应头组成,这些HTTP响应头决定浏览器是否组织前端JS代码跨域获取资源,实际情况是,前端同意请求,服务器同意响应,浏览器不同意这门亲事
浏览器的同源安全策略(端口、域名、协议有一个不同就不能通信)默认会阻止网页“跨域”获取资源,但如果接口服务器配置了CORS相关的响应头就可以解除浏览器端的跨域访问限制。就好像服务器拿着彩礼来了,浏览器就同意的这门亲事。
CORS主要在服务器端配置,客户端无需做任何处理。cors有兼容性(2022年可忽略不不计,主要是低版本服务器的兼容性)。
六、前端页面开发
页面展示:
代码:
页面:
-
<template>
-
<div class="login">
-
<div id="login_box">
-
<el-form
-
:model=
"ruleForm"
-
:rules=
"rules"
-
ref=
"ruleForm"
-
label-width=
"100px"
-
class=
"demo-ruleForm"
-
>
-
<el-form-item label="用户名" prop="username">
-
<el-input v-model="ruleForm.username">
</el-input>
-
</el-form-item>
-
<el-form-item label="密码" prop="password">
-
<el-input
-
v-model=
"ruleForm.password"
-
type=
"password"
-
show-password
-
>
</el-input>
-
</el-form-item>
-
<el-form-item label="确认密码" prop="verification" v-if="!loginstate">
-
<el-input
-
v-model=
"ruleForm.verification"
-
type=
"password"
-
show-password
-
>
</el-input>
-
</el-form-item>
-
<el-form-item>
-
<el-button type="primary" v-if="loginstate" @click="login"
-
>登录</el-button
-
>
-
<el-button type="primary" v-else @click="login">注册
</el-button>
-
<el-button @click="loginstate = !loginstate">切换{{ loginstate?'注册':'登录' }}
</el-button>
-
</el-form-item>
-
</el-form>
-
</div>
-
</div>
-
</template>
-
-
<script>
-
import { reguser }
from
"@/api/login";
-
export
default {
-
data(
) {
-
var
validatePass = (
rule, value, callback) => {
-
if (value ===
"") {
-
callback(
new
Error(
"请输入密码"));
-
}
else {
-
if (
this.
ruleForm.
verification !==
"") {
-
this.
$refs.
ruleForm.
validateField(
"verification");
-
}
-
callback();
-
}
-
};
-
var
validatePass2 = (
rule, value, callback) => {
-
if (value ===
"") {
-
callback(
new
Error(
"请再次输入密码"));
-
}
else
if (value !==
this.
ruleForm.
password) {
-
callback(
new
Error(
"两次输入密码不一致!"));
-
}
else {
-
callback();
-
}
-
};
-
return {
-
//当前的状态,true为登录
-
loginstate:
true,
-
ruleForm: {
-
username:
"",
-
password:
"",
-
verification:
"",
-
},
-
rules: {
-
username: [
-
{
required:
true,
message:
"请输入用户名",
trigger:
"blur" },
-
],
-
password: [
-
{
required:
true,
validator: validatePass,
trigger:
"blur" },
-
],
-
verification: [
-
{
required:
true,
validator: validatePass2,
trigger:
"blur" },
-
],
-
},
-
};
-
},
-
methods: {
-
login(
) {
-
//用来判断是登录还是注册
-
const { loginstate } =
this;
-
const { username, password } =
this.
ruleForm;
-
this.
$refs.
ruleForm.
validate(
(valid) => {
-
if (valid) {
-
//验证成功
-
if (loginstate) {
-
//登录
-
}
else {
-
//注册
-
const data = {
-
username,
-
password,
-
};
-
reguser(data).
then(
(res) => {
-
const {code,data}=res.
data
-
if(code===
200){
-
this.
loginstate=
true
-
this.
$message.
success(
'用户注册成功,请登录。');
-
}
else{
-
this.
$message.
error(data);
-
}
-
});
-
}
-
}
-
});
-
},
-
},
-
};
-
</script>
-
-
<style lang="less" scoped>
-
.login {
-
background:
url(
"https://cdn.pixabay.com/photo/2018/08/14/13/23/ocean-3605547_1280.jpg")
-
no-repeat;
-
background-size:
100%
100%;
-
width:
100vw;
-
height:
100vh;
-
overflow: hidden;
-
}
-
-
#login_box {
-
width:
20vw;
-
background-color:
#00000060;
-
margin: auto;
-
margin-top:
15%;
-
text-align: center;
-
border-radius:
10px;
-
padding:
50px
50px;
-
}
-
</style>
后面发现请求后后台获取不到我们传递的body参数,因为axios默认传递的post参数格式是application/json,所以我们需要进行一定的配置,
通过body-parser解决上述问题,代码:(记得先安装)
-
//导入express
-
const express =
require(
'express')
-
//引入cors解决跨域问题
-
const cors =
require(
'cors')
-
//用于解决fromdata格式数据获取不到的问题
-
const bodyParser =
require(
'body-parser');
-
//创建web服务器
-
const app =
express()
-
//解决跨域
-
app.
use(
cors())
-
//数据JSON类型
-
app.
use(bodyParser.
json());
-
//解析post请求数据
-
app.
use(bodyParser.
urlencoded({
extended:
false }));
-
//将文件部署到服务器
-
app.
use(express.
static(
'img'))
-
//配置解析表单数据(application/x-www-form-urlencoded)格式的中间件
-
app.
use(express.
urlencoded({
extended:
false }))
-
const userRouter =
require(
"./router/user")
-
app.
use(
'/api', userRouter)
-
// 通过ap.listen进行服务器的配置,并启动服务器,接收两个配置参数,一个是对应的端口号,一个是启动成功的回调函数
-
app.
listen(
9588,
() => {
-
console.
log(
'服务器启动成功');
-
})
转载:https://blog.csdn.net/ct5211314/article/details/128315082
