XMLHttpRequest简称xhr,是浏览器提供的Javascript对象。之前我们使用的都是jQuery中的Ajax,现在我们使用原生JS的Ajax
目录
1 GET请求
1.1 不带参数请求
1.2 带参数请求
2 URL的编码与解码
2.1 编码 encodeURI()
2.2 解码 decodeURI()
3 POST请求
4 模拟jQuery中的Ajax函数
5 XMLHttpRequest Level2
5.1 设置HTTP的请求时限
5.2 Formdata对象
5.2.1 简单使用
5.2.2 Formdata直接获取表单数据
5.2.3 上传文件
5.2.4 上传文件的进度
1 GET请求
1.1 不带参数请求
先看服务
前端请求
- xhr.open()中可以写大写的GET,也可以写小写的GET
- xhr.readyState与xhr.status写死就行,如果请求成功就需要这两个条件
xhr.readyState代表请求的状态,4代表请求已经完成了,除了4之外还有下面这几种状态
1.2 带参数请求
先看服务,当你传入data1和data2后,服务会将两个值变成整数然后加和,之后返回给你
get请求直接将要传递的东西放在查询字符串中就可以了,无论什么框架带参数的get请求数据实质上都是以查询字符串的形式传递的
2 URL的编码与解码
url地址中只允许出现字母,标点符号,数字,想是中文这种字符会被自动编码
比如说你在百度上搜索 我 这个汉字,实质上就会编码为%E6%88%91,一般来讲一个汉字就对应着三个百分号值
2.1 编码 encodeURI()
2.2 解码 decodeURI()
3 POST请求
服务
请求
post请求需要使用setRequestHeader()设置请求头,这个是固定写法,setRequestHeader()必须放在open()的后面,send()的前面
post要发送的数据要写在send()中
4 模拟jQuery中的Ajax函数
我们只考虑get与post的情况,需要处理的地方就是将传入的data对象转变为查询字符串的形式,判断是get还是post,除此之外简单弄一弄就行了
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body></body>
<script>function myAjax(resquest_obj) {xhr = new XMLHttpRequest()if (/^GET$/i.test(resquest_obj.type)) {send_str = ''for (i in resquest_obj.data) {send_str = send_str + i + '=' + resquest_obj.data[i] + '&'}send_str = send_str.slice(0,-1)resquest_obj.url = resquest_obj.url + '?' + send_strxhr.open(resquest_obj.type,resquest_obj.url)xhr.send()xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {resquest_obj.success(xhr.responseText)}}}else if (/^POST$/i.test(resquest_obj.type)) {xhr.open(resquest_obj.type,resquest_obj.url)xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')send_str = ''for (i in resquest_obj.data) {send_str = send_str + i + '=' + resquest_obj.data[i] + '&'}send_str = send_str.slice(0,-1)xhr.send(send_str)xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {resquest_obj.success(xhr.responseText)}}}}
</script>
</html>
搞一个服务测一下,get是两个数相加,post是两个数相乘
get
post
5 XMLHttpRequest Level2
上面我们用的都是旧版的XMLHttpRequest,旧版有两个缺点
- 无法上传文件
- 没有传送数据的进度信息
XMLHttpRequest Level2 是 XMLHttpRequest 的升级版(随着HTML5一起更新,在2014年10月28日完成更新,如果浏览器支持HTML5大概率也支持XMLHttpRequest的Level2),继承了老版本的所有用法且使用方式相同,有下面这些新的功能
- 设置HTTP请求的时限
- 使用FormData对象管理表单数据
- 可以上传文件
- 可以获得数据传输的进度信息
5.1 设置HTTP的请求时限
请求时限的属性名称是timeout,过了这个时间还没有请求完毕就中断这次请求
- 单位为毫秒
可以配套使用timeout事件,可以设置中止之后干一点儿什么
我们给一个极短的时间测试一下,比如给3ms
3ms内没有完成请求,请求就中断了自然也没有之后的响应结果。中断后触发了timeout事件,执行了timeout中的函数
在服务端虽然请求中断了,但状态码依然是200
5.2 Formdata对象
5.2.1 简单使用
Formdata对象可以更便捷的传输数据,我们简单用一下
上面这个例子中,如果使用FormData发送就不要再使用setRequestHeader()加请求头了,不然会报错
5.2.2 Formdata直接获取表单数据
- e.preventDefault()是取消默认提交行为
点击提交后得到结果
5.2.3 上传文件
后端
上传后会保存在代码同级目录下的upload_file,目前我还没上传,文件夹是空的
前端
使用input.files就可以接到选择的文件,files是一个数组一会儿我们打印出来看一下
如果数组元素<=0就是没选择文件,会提示你选择要上传的文件并中止函数
使用files[0]拿到文件加入的FormData对象中
之后直接把FormData对象传上去就行
打开后选择AJAX.jpg
上传之后在文件夹中得到了这张图
5.2.4 上传文件的进度
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>section {width:300px;height:20px;padding:2px;margin-top:20px;border:3px solid red;}div {width:0px;height:100%;background-color: red;}</style>
</head>
<body><input type="file"><button>上传文件</button><section><div></div></section><span>0%</span>
</body>
<script>btn = document.querySelector('button')input = document.querySelector('input')div = document.querySelector('div')span = document.querySelector('span')btn.addEventListener('click',function() {files = input.filesconsole.log(files)if (files.length <= 0) {return alert('请选择要上传的文件')}FormData_obj = new FormData()FormData_obj.append('file',files[0])xhr = new XMLHttpRequest()xhr.upload.onprogress = function(e) {if (e.lengthComputable) {percentComplate = (e.loaded/e.total)*100 - 1span.innerHTML = percentComplate + '%'div.style.width = percentComplate + '%'}}xhr.open('POST','http://127.0.0.1:5000/upload')xhr.send(FormData_obj)xhr.onreadystatechange = function() {if (xhr.readyState === 4 && xhr.status === 200) {console.log(xhr.responseText)span.innerHTML = '100%'div.style.width = '100%'}}})
</script>
</html>
xhr.upload.onprogress的书写位置在创建xhr对象后,xhr.open()前
使用xhr.upload.onprogress事件获取文件的上传进度,该事件的事件对象中我们用到三个属性
- e.lengthComputable 这个值是一个布尔值,如果长度可以计算就返回true,不可计算就返回false
- e.loaded 加载的字节大小
- e.total 文件的总字节大小
我们上传一个看一下,我这里有一个较大的数据集
点击上传文件时进度条会涨,底下的数值也会涨
直到最后100%
这里我将上传进度-1,因为在我的后端上传后还有保存,在其他的后端中上传后肯定也会有其他的操作,所以我等上传有响应后再将其置为100%,这样看起来比较舒服
bootstrap中有样式还不错的进度条,开发的时候可以使用一下 进度条(Progress) · Bootstrap v5 中文文档 v5.1 | Bootstrap 中文网