目录
一、jQuery 中的 AJAX
(一)get 方法
1.语法介绍
2.结果实现
(二)post 方法
1.语法介绍
2.结果实现
(三)通用型的 AJAX 方法
1.语法介绍
2.结果实现
二、AJAX 工具库 axios
(一)介绍
(二)axios 发送 AJAX 请求
1.基本语法
2.get 方法
语法
3.post 方法
语法
4.axios 发送 AJAX 请求优点
(三)axios 函数发送 AJAX 请求
1.语法
三、使用 fetch() 函数发送 ajax 请求
四、跨域
(一)同源策略
1.介绍
2.代码例子
(二)跨域
(三)解决跨域
1.JSONP 请求
介绍
如何工作
2.原生 JSONP 实现
3.利用 jQuery 发送 jsonp 请求
4.CORS 跨域设置
一、jQuery 中的 AJAX
要先去bootCDN网站中引入 jQuery
(一)get 方法
1.语法介绍
语法如下,括号里面有三个参数
第一参数:向谁发请求
第二参数:发送什么参数 是一个对象类型
第三参数:回调函数内部是响应体 data 参数是接收到的响应体,在回调函数中可以对响应体 data 做一些操作
第四参数:响应体类型通常用 ‘json’ 可以将 json 字符串进行解析 变回原来类型
$('button').eq(0).click(function () {$.get('http://127.0.0.1:8000/jquery-server', { a:100, b:200 }, function (data) {console.log(data)},'json')})
2.结果实现
用 json 返回数组 不用返回字符串
a, b参数成功发过去了,响应体也正确
控制台输出也正确,可能有警告,在引入的javascript 标签加上一个属性就行 匿名的意思crossorigin="anonymous"
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
(二)post 方法
1.语法介绍
参数看 get 方法
改成 post 就行 换成第二个按钮 eq(1) 其它都一样
但是查看请求体内容和 get 方法不一样,post 不会直接显示到 url 后面,而是显示到请求字符串中
$('button').eq(1).click(function () {$.post('http://127.0.0.1:8000/jquery-server', { a: 100, b: 200 }, function (data) {console.log(data)})},'json')
2.结果实现
(三)通用型的 AJAX 方法
1.语法介绍
和前两个方法不同,AJAX方法 参数是对象,而且 使用这个方法可以对 http 报文内部的很多属性进行修改,功能性比较强。
能进行定义的六个属性两个方法
第一属性 url:url 请求的对象
第二属性 data:发送的请求体内容 也是对象
第三属性 type:以什么方法发送 GET 类型 还是 POST 类型
第四属性 dataType:响应体结果设置 ‘json’ 类型
第五属性 timeout:设置超时时间
第六属性 header:设置自定义请求头,如果报错看之前笔记,有处理方法,是对象形式
方法一 success:回调函数 如果请求成功 成功可以对返回的响应体内容进行处理
方法二 error:回调函数 如果请求超时 就返回一个提示
$('button').eq(2).click(function () {$.ajax({//urlurl: 'http://127.0.0.1:8000/jquery-server',//参数data: { a: 100, b: 200 },// 请求类型type: 'GET',// 响应体结果dataType: 'json',// 成功的回调函数success: function (data) {console.log(data)},// 超时时间timeout:2000,// 失败的时间error: function(){console.log('出错!')},// 设置自定义请求头header: {c:100,d:100}})})
2.结果实现
查看结果:结果正确
设置延时后:
二、AJAX 工具库 axios
(一)介绍
前端热门的 AJAX 工具库,用来发送 AJAX 请求
要先去bootCDN网站中引入 axios
(二)axios 发送 AJAX 请求
比如:我们可以使用这个工具库 把 url 地址单独写出来
axios.defaults.baseURL = 'http://127.0.0.1:8000'
然后下面就不用写了,但是得写后面的 /axios-server
1.基本语法
axios.请求方法名( url地址后面部分,{里面是发送的一些参数值,可以自己设置
params:{
这里是 url 后面的传入的参数值
}
headers:{
自定义请求头
}
}).then(value => {这里面处理服务器返回的响应体(这里使用了es6 promise 语法)
console.log(value)这里的 value 是对象 里面有很多属性 包括返回来的响应体 data 能自动转换成对象
})
2.get 方法
语法
get 方法没有请求体内容 所以就按基本语法来就行
<script>const btns = document.querySelectorAll('button')axios.defaults.baseURL = 'http://127.0.0.1:8000'btns[0].onclick = function () {axios.get('/axios-server', {params: {id: 100,vip: 100},headers: {name: 'haha',age: 18}}).then(value => {console.log(value)})}</script>
3.post 方法
相比于 get 方法 还可以设置 请求体 的内容 在下面 data 部分书写
行,头,体 结构很清晰
注意结构 post 因为有响应体结构,响应体内容作为第二个参数传入进去
格式是这样的
语法
axios.post(url地址,响应体内容,(其它内容)).then((value)=> {
处理响应体内容 value(是一个对象里面包括响应体)
})
btns[1].onclick = function () {axios.post('/axios-server', {username: 'admin',password: 'admin'}, {params: {id: 100,vip: 100},headers: {name: 'haha',age: 18}}).then(value => {console.log(value)})}
结果成功返回
4.axios 发送 AJAX 请求优点
数据获取完整 value 里面有很多信息
包含 data 返回的响应体 而且是直接解析后的结果 (比如自动解析成对象)
头信息
请求的原生 ajax 对象
相应的状态码
和响应状态字符串
(三)axios 函数发送 AJAX 请求
1.语法
很简单很贴合 http 报文的格式
在 axios 里面直接写一个对象
axios({
method:’发送方法‘,
url:目标地址,
params:{
url 后缀参数
},
headers:{
自定义请求头
},
data:{
请求体
}
}).then(response=>{
返回内容 还是一个对象
内容很多可以挨个调用里面的参数使用 且都是解析好的
})
用自己的方法(一个函数来发送)
btns[2].onclick = function () {axios({method: 'post',url: '/axios-server',params: {vip: 10,level: 30},headers: {a: 100,b: 200},data: {username: 'admin',password: 'admin'}}).then(response => {console.log(123)})}
response对象中的具体内容:
状态码,响应状态字符串,响应头信息,响应体
可以用下面语句进行检查调用
结果正确
三、使用 fetch() 函数发送 ajax 请求
fetch() 属于全局变量,可以直接调用,不用去外部引用
有两个参数
一个参数是 url
另一个参数是一个对象
可以配置method发送方法 headers请求头 body请求体
返回的结果是一个 promise 对象 response 不能直接使用而是 先return response.text()
再使用一个then 方法 里面就能使用 响应体了
如果响应体是 json 字符串型 我们直接 把上面的 text() 变成 json() 就能把 json 自负床解析成正常的数据类型了
btn.onclick = function () {fetch('http://127.0.0.1:8000/fetch-server', {method: 'post',headers: {name: 'hahah'},body: 'username=admin&password=admin'}).then(response => {return response.json()}).then(response => {console.log(response)})}
四、跨域
(一)同源策略
1.介绍
同一个来源,浏览器的一种安全机制
当前网页的 url 和 AJAX 请求目标资源 (服务器)的url 必须相同
就是 url(协议、域名、端口)必须完全相同 就 满足同源策略
AJAX 默认遵顼同源策略,如果不满足发不了 AJAX 请求
2.代码例子
如果 a.com 向 b.com 发送请求 就不属于同源
下面这个例子 页面和用户数据资源都是从 9000端口来的 属于同源,可以直接发送 ajax 请求
就是使用同一个服务
这时我们可以省略 url 前面的部分 只写 ‘/data’
<body><h1>哈哈</h1><button>点击获取用户数据</button><script>const btn = document.querySelector('button')btn.onclick = function () {const x = new XMLHttpRequest();x.open('get', '/data')x.send()x.onreadystatechange = function () {if (x.readyState === 4) {if (x.status >= 200 & x.status < 300) {console.log(x.response)}}}}</script>
</body>
(二)跨域
违背同源策略就是跨域
a.com 向 b.com 发送请求
3000 端口 向 8000 端口发请求
http 协议向 https 协议发送请求
上面都属于跨域
跨域很常见 因为一台服务器不够我们使用 ,我们得添加多台主机服务器使用,有利于资源的划分,向不用服务器发送请求就会发生跨域
(三)解决跨域
外部引入的资源协议 域名 端口 都不一样,是一个跨域请求
<script crossorigin="anonymous" src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.js"></script>
1.JSONP 请求
介绍
JSONP 全称是 JSON with Padding 是非官方的跨域解决方案,只支持 get 请求
如何工作
借助 javascript 工作的
script 标签本身就具有跨域特性
通过返回一个函数调用,函数的实参就是我们想返回给客户端的数据
函数得提前声明,否则报错
让 js 进行解析就是 JSONP 的工作方法
2.原生 JSONP 实现
借助script 向服务器发送一个请求,服务器返回一个 handle 函数的调用 浏览器收到后一看能执行就进行解析和调用,数据就处理了,实现了跨域
客户端:
<body>用户名:<input type="text" id="username"><p></p><script>const p = document.querySelector('p')const input = document.querySelector('input')function handle(data) {input.style.border = 'solid 1px #f00'p.innerHTML = data.msg}input.onblur = function () {let username = this.valueconst script = document.createElement('script')script.src = 'http://127.0.0.1:8000/check-username'document.body.appendChild(script)}</script>
</body>
服务端:
app.all('/check-username', (request, response) => {const data = {exist: 1,msg: '用户名已存在'}let str = JSON.stringify(data)response.send(`handle(${str})`)
})
结果:
3.利用 jQuery 发送 jsonp 请求
客户端代码:
<script>$('button').eq(0).click(function () {$.getJSON('http://127.0.0.1:9000/jquery-jsonp-server?callback=?', function (data) {console.log(data)})})</script>
服务端代码:
const express = require('express')
const app = express()
app.all('/jquery-jsonp-server', (request, response) => {const data = {name: '地方',city: ['北京', '上海', '深圳']}let str = JSON.stringify(data)response.end(`handle(${str})`)
})
app.listen(9000, () => {console.log('服务已启动')
})
查看报文:
发现出现了一个 callback 值,是 jquery 注册的函数,回来返回这个函数的调用,前端就能对这个数据处理
在服务端加上下面的代码,把请求当中 url 中的 callback参数值 cb 取出 ,就是上一个图片中的字符串,它是一个函数
let cb = request.query.callback
使用这个调回函数返回查看
response.end(`${cb}(${str})`)
然后返回调用就变成下面的形式了
最后在客户端调用返回的数据 data 就是服务端的对象数据
<body><button>点击发送jsonp 请求</button><div id="result"></div><script>$('button').eq(0).click(function () {$.getJSON('http://127.0.0.1:9000/jquery-jsonp-server?callback=?', function (data) {$('#result').html(`名称:${data.name}<br>城市:${data.city}`)})})</script>
</body>
服务端完整代码:
const express = require('express')
const app = express()
app.all('/jquery-jsonp-server', (request, response) => {const data = {name: '地方',city: ['北京', '上海', '深圳']}let str = JSON.stringify(data)let cb = request.query.callbackresponse.end(`${cb}(${str})`)
})app.listen(9000, () => {console.log('服务已启动')
})
结果正确成功拿到结果
4.CORS 跨域设置
全称是跨域资源共享,是官方的解决方案,不同于 jsonp 是程序员自己弄出来的
不需要在客户端做操作 正常发 AJAX 请求,只在服务器中进行设置响应头就可以限制跨域
支持 get post 请求 其它也支持
客户端代码:
<script>const btn = document.querySelector('button')btn.onclick = function(){const x= new XMLHttpRequest();x.open('get','http://127.0.0.1:9000/cors-server')x.send()x.onreadystatechange = function () {if (x.readyState === 4) {if (x.status >= 200 && x.status < 300) {console.log(x.response)}}}}
服务端代码:
app.all('/cors-server', (request, response) => {response.send(`hello cors`)
})
运行报错:服务端没有返回 CORS 头报错
这是因为我们之前会加上报错红字里面的 access... 的 响应头来支持跨域,但是这次没加,看下面图片可知我们客户端是 file 协议 而 服务端 是http 协议,所以这属于一个跨域请求
我们像以前一样设置一个下面的允许跨域的响应头,允许谁向我发送请求
后面是设置允许访问的地址,* 就是允许所有地址跨域访问
response.setHeader('Access-Control-Allow-Origin', '*')
还有很多请求头可以设置,可以自己看看 就比如下面 写完下面两句话就能自定义请求头和方法不报错了
response.setHeader('Access-Control-Allow-Headers', '*')response.setHeader('Access-Control-Allow-Method', '*')
问题解决
服务端改进代码:
app.all('/cors-server', (request, response) => {response.setHeader('Access-Control-Allow-Origin', '*')response.send(`hello cors`)
})