Vue12-跨域+前端发送请求
Vue12-跨域+前端发送请求
1.前端发送请求的四种方式
- XHR,XMLHttpRequest。XHR是JS内置发送请求的方式,发送请求的过程比较繁琐,所以一般不直接使用XHR发送请求,而是对XHR封装后使用。
- jQuery。jQuery通过$.get()和$.post()发送请求,jQuery是对XHR的封装。jQuery中80%的代码用来操作DOM,20%用来发送请求的,所以如果是vue项目,没有必要为了发送请求引入jQuery。
- axios。axios是对XHR的封装,大小是jQuery的四分之一,Vue官网也推荐使用axios发送请求。
- fetch。fetch是JavaScript内置的,Window上就有fetch方法。fetch有两个问题:fetch将请求返回的数据包装了两次;fetch有兼容性问题,IE浏览器不适用。
2.跨域问题及其解决方法
- 跨域问题。前端发送请求给服务器,服务器接受到前端请求,并且正常响应,但是当浏览器拿到服务器响应的数据时发现前端地址和后端地址不符合同源策略,所有没有将数据给前端。
- 同源策略。协议、IP和端口都相同即符合同源策略,否则不符合同源策略。
- 跨域问题的解决方法。
- CORS,即后端在响应中添加Access-Control-Allow-Origin:*配置,允许任何网站访问,此时浏览器就不会拦截后端返回给前端的数据了。
- jsonp。jonsp解决跨域的原理,通过script标签的src属性不受同源策略的影响来解决跨域问题,实际项目中不经常使用。jsonp只能解决get请求的跨域问题,不能解决post、put、delete请求的跨域问题。
- 配置代理服务器。如前端的端口是8080,后端服务的端口是5000,在前端和后端之间开一个代理服务器,代理服务器和前段的协议、IP和端口都是一样的。前端请求数据先请求代理服务器,由代理服务器去请求后端服务器。返回数据时后端服务器先将数据交给代理服务器,代理服务器在将数据交给前端。由于代理服务器和前端的协议、IP、端口都是一样的,所以不存在跨域问题。同时代理服务器和后端服务器采用的是服务器之间的方式通信,所以也不存在跨域问题。生产环境中可以使用nginx当代理服务器,开发环境可以vue-cli开启代理服务器。
3.axios的使用
- 安装axios,npm i axios。
- 引入和使用axios。
import axios from 'axios'
// 使用axios发送get请求。
axios.get('http://localhost:8080/student').then(
response => {
console.log("接受到的数据", response.data);
},
error => {
console.log("错误", error.message);
}
)
4.vue配置代理的两种方式
-
vue配置代理的第一种方式。
- 配置代理并发送请求。前端地址,localhost:8080;后端地址,localhost:5000。
// vue.config.js中添加如下配置。 module.exports = defineConfig({ ...省略其他配置。 // 配置代理服务器。http://localhost:5000是后端服务地址。 devServer: { proxy: 'http://localhost:5000' } }); // 配置代理后发送请求。 // 配置代理服务后,使用axios访问localhost:8080,则代理服务器会将请求转发给localhost:5000。 axios.get('http://localhost:8080/student').then( response => { console.log("接受到数据", response.data); }, error => { console.log("错误", error.message); } )
- 优点:配置简单,将请求直接发给8080。
- 缺点:不能配置多个代理,不能配置请求是否走代理。
- 工作原理。当请求的资源前端不存在时,则将请求转发给代理服务器。
-
vue配置代理的第二种方式。
- 配置代理并发送请求。
module.exports = defineConfig({ ... 其他配置省略 devServer: { proxy: { // 请求前缀。只有前缀是/api的请求才会进行代理,并且走如下的代理。 // 即访问http://localhost:8080/api/student,会走这个代理。 // 请求这个代理转发出去的请求为 http://localhost:5000/api/student。 // 如果想让转发出去的请求为 http://localhost:5000/student // 则需要配置pathRewrite: {'^/api': ''}。 '/api': { // 后端服务地址。 target: 'http://localhost:5000', // 路径重写,将请求http://localhost:8080/api/student重写为/api/student // 经过重写之后的路径是 /student pathRewrite: {'^/api': ''}, ws: true, // 用于支持websocket // 前端localhost:8080,后端localhost:5000。 // changeOrigin: true,请求头中的host是localhost:5000。即后端获取的请求地址就是localhost:5000 // changeOrigin: false,请求头中的host是localhost:8080。 // changeOrigin的默认值时true。 changeOrigin: true // 用于控制请求头中的host字段,即控制请求从哪里来。 } } } }); // 发送请求。 axios.get('http://localhost:8080/api/student').then( response => { console.log("接受到数据", response.data); }, error => { console.log("错误", error.message); } )
- 优点:可以配置多个代理,并且可以灵活的控制请求是否走代理。
- 缺点:配置繁琐,需要对请求路径进行重写。
5.Github用户搜索案例
- public下新建css文件夹,放入bootstrap.css文件,然后在public/index.html中引入。
<link rel="stylesheet" href="<%= BASE_URL %>css/bootstrap.css">
- main.js。
import Vue from 'vue'
import App from './App'
new Vue({
el: '#app',
render: h => h(App),
beforeCreate() {
Vue.prototype.$bus = this;
}
});
- App.vue。
<template>
<div id="container">
<Search/>
<List/>
</div>
</template>
<script>
import Search from "./components/Search";
import List from "./components/List";
export default {
name: "App",
components: {List, Search}
}
</script>
- Search.vue。
<template>
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Users</h3>
<div>
<input type="text" placeholder="enter the name you search" v-model="keyWord"/>
<button @click="getUserData">Search</button>
</div>
</section>
</template>
<script>
import axios from 'axios'
export default {
name: "Search",
data() {
return {
keyWord: '',
}
},
methods: {
getUserData() {
// 发送请求前使用全局事件总线更新List组件页面为加载数据中。
this.$bus.$emit('updateInfo', {
isFirst: false,
isLoading: true,
errorMessage: '',
users: []
});
// https://api.github.com/search/users是一个公共的接口,内部通过CORS解决了跨域问题。
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
response => {
console.log('请求数据成功');
this.$bus.$emit('updateInfo', {
isLoading: false,
errorMessage: '',
users: response.data.items
});
},
error => {
console.log('请求错误');
this.$bus.$emit('updateInfo', {
isLoading: false,
errorMessage: error.message,
users: []
});
}
)
}
}
}
</script>
<style scoped>
</style>
- List.vue。
<template>
<div class="row">
<!-- 用户列表 -->
<div v-show="info.users.length" class="card" v-for="user in info.users" :key="user.login">
<a target="_blank" :href="user.html_url">
<img :src="user.avatar_url" style='width: 100px'/>
</a>
<p class="card-text">{{ user.login }}</p>
</div>
<h2 v-show="info.isFirst">欢迎使用</h2>
<h2 v-show="info.isLoading">数据加载中</h2>
<h2 v-show="info.errorMessage">请求出错</h2>
</div>
</template>
<script>
export default {
name: "List",
data() {
return {
info: {
// 是否是第一次进入该网站
isFirst: true,
// 发送请求后,数据正在加载。
isLoading: false,
// 错误信息
errorMessage: '',
// 用户数据
users: []
}
}
},
mounted() {
this.$bus.$on('updateInfo', (info) => {
console.log('List组件收到数据');
// 使用ES6的语法更新数据。
// {...this.info, ...info}表示将数据this.info和info展开,然后使用info中的
// 属性覆盖this.info中的属性。如果this.info中有属性isFirst,但是info中没有
// 属性isFirst,则不会更新this.info中的isFirst属性。
this.info = {...this.info, ...info};
})
}
}
</script>
<style scoped>
.album {
min-height: 50rem; /* Can be removed; just added for demo purposes */
padding-top: 3rem;
padding-bottom: 3rem;
background-color: #f7f7f7;
}
.card {
float: left;
width: 33.333%;
padding: .75rem;
margin-bottom: 2rem;
border: 1px solid #efefef;
text-align: center;
}
.card > img {
margin-bottom: .75rem;
border-radius: 100px;
}
.card-text {
font-size: 85%;
}
</style>
6.vue-resource简介
- vue-resource是vue提供的一个发送ajax请求的插件。早起由vue团队维护,但是现在官方已经不维护了,由其他团队维护。
- vue-resource在vue早起1.x版本使用的还是挺多的,所以很多的老项目可能会用到,需要了解。
- vue-resource也是对XHR的封装。
7.vue-resource的安装和使用
- 安装vue-resource插件,npm i vue-resource。
- main.js中引入vue-resource,import vueResource from 'vue-resource'。
- main.js中使用vue-resource插件,Vue.use(vueResource),使用之后VueComponent实例对象上就会多一个属性$http。
8.Github案例改写-使用vue-resource发送请求
- 修改Search.vue中发送请求的getUserData()函数。
getUserData() {
// 使用vue-resource后,VueComponent上多了$http属性。
console.log(this);
this.$bus.$emit('updateInfo', {
isFirst: false,
isLoading: true,
errorMessage: '',
users: []
});
this.$http.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
response => {
console.log('请求数据成功');
this.$bus.$emit('updateInfo', {
isLoading: false,
errorMessage: '',
users: response.data.items
});
},
error => {
console.log('请求错误');
this.$bus.$emit('updateInfo', {
isLoading: false,
errorMessage: error.message,
users: []
});
}
)
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现