服务端跨域资源共享问题

在客户端请求服务端接口的时候,可能会跨域,提示被 CORS 阻止了。这个时候服务端需要在做出响应的时候在头部添加一个 ‘Access-Control-Allow-Origin’ ,用这个头部去设置服务端允许访问的域。
在 node 服务端,安装 cors 这个包,然后在 index 文件中使用。

1
2
3
4
5
6
7
8
9
10
import cors from 'cors';
/**
* 跨域资源共享
*/
app.use(
cors({
origin: "*", //允许所有域访问
exposedHeaders: "X-Total-Count", //设置允许的自定义的头部
})
);

安装与使用 http 客户端请求服务端接口(axios)

安装 axios: npm install axios
使用的时候:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template>
<h3>{{ name }}</h3>
<div v-for="post in posts" :key="post.id">
{{ post.title }} - <small>{{ post.user.name }}</small>
</div>
</template>

<script>
import axios from 'axios';
export default {
data() {
return {
name: '你好啊',
posts: [],
};
},
created() {
axios.get('http://localhost:3000/posts').then(response => {
console.log(response);
this.posts = response.data;
}).catch(error=>{
console.log(error.message)
console.log(error.response)
});
},
};
</script>

处理在 Vue 应用里使用 axios 发送请求时发生的错误

处理错误写在 catch 区块中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<template>
<h3>{{ name }}</h3>
<div>
{{ errorMessage }}
</div>
<div v-for="post in posts" :key="post.id">
{{ post.title }} - <small>{{ post.user.name }}</small>
</div>
</template>

<script>
import axios from 'axios';
export default {
data() {
return {
name: '你好啊',
posts: [],
errorMessage: '',
};
},
created() {
axios
.get('http://localhost:3000/posts1')
.then(response => {
console.log(response);
this.posts = response.data;
})
.catch(error => {
console.log(error.message);
console.log(error.response);
this.errorMessage = error.message;
});
},
};
</script>

使用 async、await 处理 axios 请求

改造一下请求方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
<h3>{{ name }}</h3>
<div>
{{ errorMessage }}
</div>
<div v-for="post in posts" :key="post.id">
{{ post.title }} - <small>{{ post.user.name }}</small>
</div>
</template>

<script>
import axios from 'axios';
export default {
data() {
return {
name: '你好啊',
posts: [],
errorMessage: '',
};
},
async created() {
try {
const response = await axios.get('http://localhost:3000/posts');
this.posts = response.data;
} catch (error) {
this.message = error.message;
}
},
};
</script>

axios 请求的配置

在 axios 里可以添加请求的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
async created() {
try {
const response = await axios({
method: 'get', //请求方法
url: '/posts', //接口地址
baseURL: 'http://localhost:3000', //请求基础地址
headers: {
'X-Custom': 'hello~',
},
});
this.posts = response.data;
} catch (error) {
this.message = error.message;
}
},

axios 默认的配置

修改默认的配置,每次请求就不用带基本地址了。新建个 app.service.ts:

1
2
3
4
5
import axios from 'axios';

axios.defaults.baseURL = 'http://localhost:3000';

export { axios };

使用的时候:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
import { axios } from '@/app/app.service'; //导入
export default {
data() {
return {
name: '你好啊',
posts: [],
errorMessage: '',
};
},
async created() {
try {
const response = await axios.get('/posts'); //不用带基本地址了
console.log(axios.defaults); //打印axios的默认配置
this.posts = response.data;
} catch (error) {
this.message = error.message;
}
},
};
</script>

axios 的请求与响应的拦截器

在 axios 发送请求前和收到响应后,我们可以去设置一些拦截器,可以拦截请求和响应。你可以在这些拦截器里,提前处理一下请求和响应。拦截器的设置:
app.service.ts 中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import axios from 'axios';

axios.defaults.baseURL = 'http://localhost:3000';

/**
* 请求拦截器
*/

axios.interceptors.request.use(
config => {
//正常请求用的回调,支持一个config参数,值是axios用的请求的配置
console.log('axios请求拦截器', config);
return config;
},
error => {
return Promise.reject(error);
},
);

/**
* 响应拦截器
*/
axios.interceptors.response.use(
response => {
console.log('axios响应拦截器', response);
return response;
},
error => {
return Promise.reject(error);
},
);

export { axios };

在请求的时候和响应的时候 ,会看到控制台打印出了相关的东西。


创建与使用 axios 实例

app.service.ts:

1
2
3
4
5
6
/**
* axios实例
*/
const apiHttpClient = axios.create({
baseURL: 'http://localhost:3000',
});

使用和正常 axios 一样:

1
2
3
4
5
6
7
8
9
async created() {
try {
const response = await apiHttpClient.get('/posts');
// console.log(axios.defaults);
this.posts = response.data;
} catch (error) {
this.message = error.message;
}
},

发送 post 类型的 http 请求

1
2
3
4
5
6
7
8
9
//用户登录
try {
const response = await apiHttpClient.post('/login', this.user);
this.token = response.token;

console.log(response.data);
} catch (error) {
this.errorMessage = error.message;
}

在请求里配置头部数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
async createPost() {
try {
const response = await apiHttpClient.post(
'/posts',
{
title: this.title,
},

//post的第三个参数是配置项,可以在里面配置headers
{
headers: {
Authorization: `Bearer ${this.token}`,
},
},
);
console.log(response.data);

this.title = '';

this.getPosts();
} catch (error) {
this.errorMessage = error.message;
}
},

发送 patch/put 类型的 http 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
async updatePost(event, postId) {
try {
await apiHttpClient.patch(
`/posts/${postId}`,
{
title: event.target.value,
},
{
headers: {
Authorization: `Bearer ${this.token}`,
},
},
);
this.getPosts();
} catch (error) {
this.errorMessage = error.message;
}
},

发送 delete 类型的 http 请求

1
2
3
4
5
6
7
8
9
10
11
12
async deletePost(postId) {
try {
await apiHttpClient.delete(`/posts/${postId}`, {
headers: {
Authorization: `Bearer ${this.token}`,
},
});
this.getPosts();
} catch (error) {
this.errorMessage = error.message;
}
},