AJAX(二) axios、fetch发送请求,同源策略,跨域解决方案等
目录
1.axios函数
(1)发送get请求
(2)发送post请求
(3)axios函数发送请求
2.fetch函数(较少使用)
(二)跨域
1.同源策略
(1)概念
(2)案例证明
2.解决跨域的方案
(1)JSONP
(2)CORS
(一)其他函数的AJAX请求发送
1.axios函数
引入axios方法:
- 在<head>里引入<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.js"></script>(bootstrap网站里找)
- 下载axios:npm install axios -g
推荐第一种方法
服务端:
app.all('/axios-server', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 设置响应头 允许任意类型的请求头
response.setHeader('Access-Control-Allow-Headers', '*')
// 设置发送
response.send('response from axios!')
})
(1)发送get请求
// 点击get发送请求
btns[0].addEventListener('click', function () {
// get请求
axios.get('/axios-server', {
// url参数
params: {
id: 123,
vip: true
},
// 请求头信息
headers: {
Name: 'csq',
Age: 18
}
}).then(response => (
console.log(response) //获取响应结果 promise的then函数
))
})
promise的then()函数,现在还不清楚具体的功能和原理,学完ajax就补
用于获取响应体的信息
(2)发送post请求
// 点击post发送请求
btns[1].addEventListener('click', function () {
// 发送post 格式:post(url{},{请求体data},{其他参数})
axios.post('/axios-server', {
// 请求体
uname: 'admin',
pwd: '123'
}, {
// 其它参数
// url参数
params: {
id: 1,
vip: true
},
// 请求头
headers: {
Name: 'csq',
Age: 18
}
})
})
格式:post(url{},{请求体data},{其他参数})
(3)axios函数发送请求
// 点击ajax 用axios函数发送请求
btns[2].addEventListener('click', function () {
axios({
// 发送方式(默认get)
method: 'POST',
// url
url: '/axios-server',
// url参数
params: {
id: 1,
vip: true
},
// 请求头
headers: {
Name: 'csq',
Age: 18
},
// 请求体
data: {
uname: 'admin',
pwd: '123'
}
}).then(response => {
// promise 获取数据
console.log(response)
console.log(response.status)
console.log(response.statusText)
console.log(response.headers)
console.log(response.data)
console.log(response.config.headers.Name)
})
})
2.fetch函数(较少使用)
服务端:
// fetch函数 响应路由规则
app.all('/fetch-server', (request, response) => {
// 设置响应头 设置允许跨域
response.setHeader('Access-Control-Allow-Origin', '*')
// 设置响应头 允许任意类型的请求头
response.setHeader('Access-Control-Allow-Headers', '*')
// 设置发送
response.send('response from fetch!')
})
// fetch函数发送请求
btn.addEventListener('click', function ()
fetch('http://127.0.0.1:8000/fetch-server', {
// 发送方式
method: 'POST',
// url参数
params: {
id: 123,
vip: true
},
// 请求头信息
headers: {
Name: 'csq',
Age: 18
},
// 请求体 字符串类型 还有别的类型:formData等
body: 'uname=admin&pwd=123'
// 响应体的结果获取 then返回promise类型
}).then(response => {
return response.text()//转换成字符串类型
// return response.json() //转换成json类型
}).then(response => {
console.log(response)
})
})
此处使用两个then()函数
(二)跨域
1.同源策略
(1)概念
同源策略是浏览器最核心最基本的安全功能
如果2个URL的协议、域名(主机)、端口号都相同,则称它们同源
同源策略是浏览器的行为,是为了保护本地数据不被JavaScript代码获取回来的数据污染
如果非同源(即跨域),那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问,因此拦截的是客户端发出的请求回来的数据接收,即请求发送了,服务器响应了,但是无法被浏览器接收
跨域不能进行如下操作:
- Cookie、LocalStorage 和 IndexDB 无法读写
- DOM 和 Js对象无法获得
- AJAX请求不能发送
可以跨域的标签:
在浏览器中, <script> 、<img>、<iframe>、<link>等标签都可以跨域加载,而不受浏览器的同源策略的限制, 这些带src属性的标签每次加载的时候,实际上都是浏览器发起一次GET请求, 不同于普通请求(XMLHTTPRequest)的是,通过src属性加载的资源,浏览器限制了JavaScript的权限,使其不能读写src加载返回的内容
(2)案例证明
服务端:
// 1.引入express
const express = require('express')
// 2.创建初始对象
const app = express()
// 3.路由机制 get
app.get('/server', (request, response) => {
// 发送文件 __dirname:绝对路径 D:\ajax\跨域\1.同源策略
response.sendFile(__dirname + '/index.html')
})
// /data
app.get('/data', (request, response) => {
response.send('数据来了数据来了')
})
// 4.端口监听事件
app.listen(8000, () => {
console.log('服务器8000端口正在运行中...')
})
发送文件:sendFile(__dirname+'文件名')
index.html文件 :
<!-- 引入axios -->
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.6/axios.js"></script>
</head>
<body>
<h1>同源策略</h1>
<button>点击发送请求</button>
<script>
// 点击按钮发送请求
const btn = document.querySelector('button')
// 用axios函数发送ajax
btn.addEventListener('click', function () {
// 因为同源,故url路径可省略简写为/data即可
axios.get('/data', {}).then(response => {
console.log(response.data)
})
})
</script>
</body>
index.html和服务端server.js同源,点击按钮发送请求正确
若将index.html以liveServer形式打开,因为liveServer用的是5500端口,则与服务端不同源
报错,不能发送ajax请求(maybe)
2.解决跨域的方案
(1)JSONP
原理:动态创建script标签,src属性指向没有跨域限制;指向一个接口,接口返回的格式一定是函数表达式(数据)
jsonp的使用:
1、动态创建script标签
const script = document.createElement('script')
2、添加script路径
script.src = 'server.js的路径'
3、将script标签插入到目标位置
document.body.appendChild(script
jsonp的缺点
1、只支持get请求,不支持post等请求
2、多次点击后页面会存在大量废弃script标签,使用onload事件在script标签作用后立即删除
案例分析
输入用户名,若已经存在则输入框边框变为红色,提示用户名已存在
<body>
<input type="text">
<p></p>
<script>
// 判断输入的内容在服务端内是否存在,不存在则输入框变为红色边框,文字提示重复
const ipt = document.querySelector('input')
const p = document.querySelector('p')
// 失去焦点事件 用change/blur
ipt.addEventListener('change', function () {
// 动态创建script标签
const script = document.createElement('script')
// 写src
script.src = 'http://127.0.0.1:8000/check-uname'
// 将标签写到p标签后
document.body.appendChild(script)
})
// 声明handle函数
function handle(data) {
// 如果值相等表明重复
if (data.uname === ipt.value) {
p.innerHTML = data.msg
p.style.color = 'red'
ipt.style.border = '2px solid red'
} else {
p.innerHTML = ''
ipt.style.border = '1px solid #000'
}
}
</script>
</body>
服务端:
// 1.引入express
const express = require('express')
// 2.创建初始对象
const app = express()
// 3.路由机制 get
app.get('/check-uname', (request, response) => {
const data = {
uname: 'csq',
age: 18,
msg: '输入用户名已存在!'
}
// 将对象转换为字符串
let str = JSON.stringify(data)
// 调用handle函数
response.send(`handle(${str})`)
})
// 4.端口监听事件
app.listen(8000, () => {
console.log('服务器8000端口正在运行中...')
})
弊端:
多次进行get请求后页面会留存大量script标签,造成大量冗余
解决方法:用onload事件,即用即删,script标签完全加载完毕后触发
// 失去焦点事件 用change/blur
ipt.addEventListener('change', function () {
// 1.动态创建script标签
const script = document.createElement('script')
// 2.写src
script.src = 'http://127.0.0.1:8000/check-uname'
// 3.将标签写到p标签后
document.body.appendChild(script)
// 多次请求get事件后,页面留存大量script标签
// 4.用onload事件,即用即删
script.addEventListener('load', function () {
script.remove()
})
})
此时script标签已删除
(2)CORS
跨域资源共享是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他 源(域、协议或端口),使得浏览器允许这些源访问加载自己的资源
CORS工作原理:
通过设置一个响应头来告诉浏览器该请求允许跨域,浏览器接收到该响应后就会响应对方
允许跨域的响应头
response.setHeader('Access-Control-Allow-Origin','*')
更多响应头见下方链接
跨源资源共享(CORS) - HTTP | MDN
(三)小感悟
终于算是肤浅的学完了ajax?还有很多细节不熟悉,等以后遇到了具体的再补吧,学前端进度还不到30%...继续加油!!!
遛达西: 写的不错。 新版的 react router 还算可以,比之前的好用不少。 感谢 hooks
普通网友: 文章结构严谨有条,层次分明,读起来一点也不费劲,让人受益匪浅。【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】
普通网友: 大佬的文章写的太精辟了 让我深刻了解了这篇文章的精髓 谢谢大佬分享,希望继续创作优质博文。【我也写了一些相关领域的文章,希望能够得到博主的指导,共同进步!】
CSDN-Ada助手: 恭喜你这篇博客进入【CSDN每天值得看】榜单,全部的排名请看 https://bbs.csdn.net/topics/618720958。
CSDN-Ada助手: 恭喜您写了第19篇博客,看来您对Vue2项目实战的经验丰富啊!搜索界面模块的实战经验对于我来说非常有用,谢谢您的分享。希望您能继续分享更多实战经验,比如其他模块的实现或者一些优化技巧,这样能让我们有更多的学习收获。期待您的下一篇博客!