Vue 中的Ajax
配置代理
发送ajax请求的方式:
1.xhr new XMLHttpRequest()
-
xhr.open() 配置请求信息
-
xhr.send() 发送请求
-
虽是鼻祖,但很麻烦,一般对其进行二次封装
2.jQuery
-
$.get
-
$.post
-
jQuery的核心是 DOM操作,在vue等框架中不常使用
3.axios
-
与jQuery相比的优势是 promise风格
-
支持请求拦截器和响应拦截器
-
体积小
4.fetch
-
jQuery和axios 都是对xhr的封装,fetch是与xhr平级
-
是 promise风格
-
会包两层 promise
-
兼容性较差
下面解决 ajax 请求跨域问题
<template>
<div>
<button @click="sendRequest">点击发送请求</button>
</div>
</template>
<script>
import axios from "axios";
export default {
name:'App',
methods:{
sendRequest(){
axios.get('http://localhost:5000/students').then(
response =>{
console.log("请求成功,", response.data)
},
error =>{
console.log("请求失败",error.message)
}
)
}
}
}
</script>
上面是没有解决跨域问题
结果是请求失败
所谓跨域就是违背了同源策略
同源策略规定 协议名、主机名、端口号必须一致
目前的情况是 http://localhost:8080 向 http://localhost:5002 发送请求,所以跨域了
请求也发了,服务器也回应了,但是浏览器发现跨域后,没有把数据返回
如何解决?
-
用 cors,服务器返回的时候携带了一些特殊的响应头,所以能收到发来的数据
-
用 jsonp,借助了script标签里面的src 属性在引入外部资源时不受同源限制 来解决的,只能解决get请求
-
配置一台代理服务器,代理服务器和主机所处的端口相同,主机想要访问数据时,直接向代理服务器发送请求,代理服务器再向服务器请求
代理服务器和服务器打交道不用ajax请求
开启代理服务器的方法
-
nginx
-
vue-cli
在vue.config.js 文件中配置
// 开启代理服务器
devServer:{
proxy:'http://localhost:5002'
}
在请求时 请求8080端口
axios.get('http://localhost:8080/students').then(
response =>{
console.log("请求成功,", response.data)
},
error =>{
console.log("请求失败",error.message)
}
)
这时就可以请求到数据了
当你请求的资源本身就有,就不会转发给5002服务器了
用这种方式不能配置多个代理,并且不能灵活控制是否向服务器发送请求
还有第二种方式配置代理服务器,能够解决配置多个服务器,并且可以控制是否发送请求
// 方式二
devServer:{
proxy:{
'/api':{
target:'http://localhost:5002',
pathRewrite:{'^/api' : ''},
ws:true, //用于支持websocket
changeOrigin:true //用于控制请求中的host值
},
'/api1':{
target:'http://localhost:5001',
pathRewrite:{'^/api' : ''},
ws:true, //用于支持websocket
changeOrigin:true //用于控制请求中的host值
}
}
}
./api 代表的是除了 协议名主机名端口号之外的前缀,只要你的请求中带有这个前缀那么就走代理服务器,向服务器发送请求,请求的服务器地址是 target
这里有个问题,你的请求中是带有 ./api前缀的,那么请求到服务器也会有这个前缀,所以会报找不到资源
这时用 pathRewrite 将前缀替换成 空字符串即可
changeOrigin 如果是 true,那么服务器收到的请求的host 就是服务器的host,否则就是8080,默认值是true
axios.get('http://localhost:8080/api/students').then(
response =>{
console.log("请求成功,", response.data)
},
error =>{
console.log("请求失败",error.message)
}
)
请求时的路径要带前缀 /api
插槽
默认插槽
插槽可以动态地将不同的模板插入到指定的位置
下面用一个分类案例引入插槽
一开始是三个分类,分类中是 一个列表,展示每个分类的具体内容
<template>
<div class="container">
<Category title="美食" :listData="food"/>
<Category title="游戏" :listData="game"/>
<Category title="影视" :listData="movie"/>
</div>
</template>
在App组件中引入定义的 Category 组件,传入数据
<template>
<div class="category">
<h3>{{title}}分类</h3>
<ul>
<li v-for="(item,index) in listData" :key="index">{{item}}</li>
</ul>
</div>
</template>
在 Category 组件的模板中,定义有一个标题和列表,效果如图
现在的需求改变了,想让 美食分类中只展示一张图片,影视分类展示一段视频,游戏分类不变,这时就用到插槽
首先在Category 组件中,把原先的列表删除,取而代之的是 <slot> 标签,标签里面是默认内容
<template>
<div class="category">
<h3>{{title}}分类</h3>
<slot>默认内容,什么都不传就会展示</slot>
</div>
</template>
然后在引入 Category 的地方,在 Category 组件标签里添加标签体内容,内容就是想要展示的内容
<template>
<div class="container">
<Category title="美食" :listData="food">
<img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg">
</Category>
<Category title="游戏" :listData="game">
<ul>
<li v-for="(item,index) in game" :key="index">{{item}}</li>
</ul>
</Category>
<Category title="影视" :listData="movie">
<video controls src="https://haokan.baidu.com/v?vid=18035948914920602112&tab=recommend"></video>
</Category>
</div>
</template>
slot 标签就是在Category 标签中占个位,等待去填充
具名插槽
具名插槽就是拥有名字的插槽,可以指定什么内容往哪个插槽里放
如果想要在内容下面再追加一些内容的话,可以再定义一个插槽,这时存在的两个插槽就要给他们定义名字,否则就会把模板往这两个插槽中放两份
<template>
<div class="category">
<h3>{{title}}分类</h3>
<slot name="center">1默认内容,什么都不传就会展示</slot>
<slot name="footer">2默认内容,什么都不传就会展示</slot>
</div>
</template>
用name属性去定义 slot的名字
在使用组件的地方使用 slot 属性指定往哪个插槽中插入
<Category title="美食" :listData="food">
<img slot="center" src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg">
<a slot="footer" src="www.baidu.com">跳转到百度</a>
</Category>
指定slot 的时候 还有另外一种写法
就是 用 v-slot:center 用 v-slot 直接绑定某个插槽的名字
这种写法只能使用于 template 标签
作用域插槽
当数据在组件定义的地方,而组件的结构是由组件使用者来决定的,那么组件的使用者在使用组件时就获取不到组件中的数据,这时可以用作用域插槽
在组件定义的地方,也就是用 slot标签占位的地方,把数据给组件使用者传递过去
<template>
<div class="category">
<h3>{{title}}分类</h3>
<slot :games="game">1默认内容,什么都不传就会展示</slot>
</div>
</template>
在使用组件的地方,用scope 或 slot-scope 接收,这里需要注意 必须在template 标签中写这两个属性
属性值可以随意起,它接收到的是一个对象,里面就有组件传递过来的数据
<template>
<div class="container">
<Category title="游戏">
<template scope="appGame">
<ul>
<li v-for="(item,index) in appGame.games" :key="index">{{item}}</li>
</ul>
</template>
</Category>
<Category title="游戏" >
<template scope="appGame">
<ol>
<li v-for="(item,index) in appGame.games" :key="index">{{item}}</li>
</ol>
</template>
</Category>
<Category title="游戏">
<template scope="appGame">
<h4>
<li v-for="(item,index) in appGame.games" :key="index">{{item}}</li>
</h4>
</template>
</Category>
</div>
</template>
总结
作用:让父组件可以向子组件指定位置插入html结构,也是组件间通信的方式