配置代理
首先:说明以下常用的发送AJAX请求的方式:
- xhr 即XMLHttpRequest()
- jQuery g e t . get. get.post ; 对xhr进行了封装 ; 需要操作DOM,但Vue中避免操作DOM
- axios 和jQuery一样都对xhr进行了封装,且axios体积小
- fetch 兼容性比较差
所以用axios发送请求,首先需要下载axios库,并引入
要求:
目前所在端口号为8080,需要向端口号为5000的服务器请求数据。
请求发送给服务器,服务器把数据给浏览器,但不会把数据呈现在页面上,因为端口号不一样,属于跨域。
因此需要解决跨域问题,有以下几种方法:
- cors 需要在服务器里加响应头(后端)
- jsonp 借助script标签里的src属性,在引入外部资源时不受同源策略的限制 (前端+后端,且只能解决get请求)
- 代理服务器 (代理服务器端口号和浏览器一样)
使用第三种方案,即开启代理服务器,开启代理服务器有两种方式,分别是nginx和Vue CLI,这里用 Vue CLI
Vue CLI有两种不同实现方式:
配置代理一
step1:开启代理服务器(Vue.config.js)
// 开启代理服务器
devSever:{
proxy:"http://localhost:5000"
// 写代理服务器发送给请求的服务器端口号
}
ps:开启之后重启脚手架
step2:请求数据(App.vue)
import axios from "axios" //引入axios库
......
methods:{
getStudents(){
axios.get("http://localhost/8080/students").then( //向代理服务器8080要数据
response=>{console.log("请求成功",response.data)} ,
error=>{console.log("请求失败",error.message)}
)
}
但有一种情况:当public根目录下有一个Students文件,这是代理服务器不会像服务器请求数据,而直接把public根目录下的Students文件里的数据发送给浏览器。
当出现这种情况,可用下面的方法:
配置代理二
step1:开启代理服务器(Vue.config.js)
// 开启代理服务器(第二种方法)
devServer:{
proxy:{
'/demo':{ //自定义,匹配所有以“/demo”开头的请求路径
target:"http://localhost:5000",
pathRewrite:{'^/demo':''}, //这里使用了正则表达式;如果不加这行代码请求的是/demo/students,加了之后请求的是/students
ws:true, //用于支持websocket
changeOrigin:true //用于控制请求头中的host值
},
'/demo2':{} //可以配置多个代理
}
step2:请求数据(App.vue)
import axios from "axios" //引入axios库
......
methods:{
getStudents(){
axios.get("http://localhost/8080/demo/students").then( //用配置代理方式2时,需要在端口号后面加上打开代理时所匹配的请求路径据
response=>{console.log("请求成功",response.data)} ,
error=>{console.log("请求失败",error.message)}
)
}
根据具体情况判断使用哪种方法
总结:
第一种方法不可以配置多个代理但是配置代码简单,第二种方法可以决定走不走代理以及配置多个代理但是配置比较繁琐
github搜索案例练习
要求实现:在输入框输入想查询的github用户名称,点击搜索按钮可以在下方显示
并对案例进行完善:在打开页面没有用户信息时显示:欢迎使用;在点击按钮获取用户信息时显示:加载中;在请求错误时显示错误信息
首先我拆分了两个组件,分别是MyList.vue和MySearch.vue
MyList.vue:
<template>
<div class="row">
<!-- step7:对案例进行完善:再打开页面没有用户信息时显示:欢迎使用;在获取用户信息时显示:加载中;在请求错误时显示错误信息-->
<!-- step6:将相同样式的每一项删除,留下一项进行遍历,并且修改其中的信息使其呈现在页面 -->
<!-- 根据控制台每一个item中属性填写。例如在github中用户名是login -->
<div class="card" style="width: 18rem;" v-for="user in Info.users" :key="user.login">
<div class="col-lg-4">
<a :href="user.html_url" target="_blank">
<img :src="user.avatar_url" style="width:190px"/>
</a>
<p class="card-text">{{user.login}}</p>
</div>
</div>
<!-- 展示欢迎词 -->
<h1 v-show="Info.isFirst">欢迎使用</h1>
<!-- 展示加载中 -->
<h1 v-show="Info.isLoading">加载中...</h1>
<!-- 展示错误信息 -->
<h1 v-show="Info.errMsg">{{Info.errMsg}}</h1>
</div>
</template>
<script>
export default {
name:"MyList",
data(){
return {
Info:{ //step10:批量替换
// step8:做准备
isFirst:true, //第一次打开页面显示欢迎使用,点了搜索按钮就应该变为false
isLoading:false, //点了搜索按钮数据还没请求回来
errMsg:'',
users:[] //step1:从github上获取用户数据。当点击搜索按钮获取
}
// step2:根据github官网提供的接口:https://api.github.com/search/users?q=xxx,xxx表示用户输入的查询内容。所以需要先获取表单中输入的内容。
// ps:不用解决跨域问题,因为有工作人员用cors在服务器里加了响应头
}
},
mounted(){
// step4-1:绑定
// this.$bus.$on("UsersInfo",(users)=>{
// // step5:将获取到的users保存到data配置项中的users
// this.users=users
// })
// step9:更新列表中的数据(完善信息)
this.$bus.$on("updateListData",(dataObj)=>{
this.Info=dataObj
})
}
}
</script>
<style>
.album {
min-height: 50rem;
padding-top: 3rem;
padding-bottom: 3rem;
background-color: #f7f7f7;
}
.card {
float:left;
width: 33.333%;
padding: .7333rem;
margin-bottom: 2rem;
border: 1px solid #efefef;
text-align:center;
}
.card > img {
margin-bottom: .75rem;
border-radius: 100px;
}
.card-text {
font-size: 85%;
}
</style>
MySearch.vue
<template>
<section class="jumbotron">
<h3 class="display-4"> Github Users Search</h3>
<!-- step3: v-model="keywords"获取表单中查询的信息-->
<input type="text" placeholder="enter the name you " class="form-control login" v-model="keywords">
<!-- 给按钮一个点击事件,点击按钮进行发出请求 -->
<button type="button" class="btn btn-light btn-style" @click="searchUsers">Search</button>
</section>
</template>
<script>
import axios from "axios" //引入axios库
export default {
name:"MySearch",
// step3:
data(){
return {
keywords:"",
}
},
methods:{
searchUsers(){
// step9-1:点击按钮,但未请求到数据时
this.$bus.$emit("updateListData",{isFirst:false,isLoading:true,errMsg:"",users:[]})
// "https://api.github.com/search/users?q=this.keywords"这样写得到的是this.keywords字符串,要用模板字符串
axios.get(`https://api.github.com/search/users?q=${this.keywords}`).then(
response=>{
// console.log("请求成功",response.data.items)
// step4-2:触发
// this.$bus.$emit("UsersInfo",response.data.items)
// }, //只写response.data得到除了items数据外还有别的数据,但只需要items,所以写response.data.items
// step9-2:请求成功:
this.$bus.$emit("updateListData",{isFirst:false,isLoading:false,errMsg:"",users:response.data.items})
},
// step9-3:请求失败:
error=>{
this.$bus.$emit("updateListData",{isFirst:false,isLoading:false,errMsg:error.message,users:[]})
}
)
} //step4:接下来实现将请求得到的items数据放到MyList组件中。需要完成两个组件的通信,用全局事件总线
// MySearch传数据,触发事件。MyList接收数据,绑定事件
}
}
</script>
<style>
效果图: