导航:
FormData
XMLHttpRequest
上传前预览图片和文件
上传进度信息
下载进度信息
new Image()
最后: 完整示例
(1) FormData()对象
提供一种表示表单数据的键值对构造方式,即用键值对来模拟一系列表单控件
( 即: 把form中所有表单元素的 name 和 value 组装成一个queryString )
- 特点:相对于普通的ajax,使用FormData最大的优点是可以 - 异步上传二进制文件
- 如果表单的
enctype
属性设置为multipart/form-data
,则会使用表单的submit()方法来发送数据,即会使用和表单一样的格式 - 可以使用XMLHttpRequest的
send()
方法来异步的提交这个"表单"
FormData对象如何使用?
-
FormData对象的方法都在原型链条上,自身没有任何属性和方法
const formData = new FormData() ----------- FormData构造函数生成一个新的 FormData 对象
formData.append('name', 'wang') ----------- 添加数据
//通过append(key, value)来添加数据,如果 key不存在则会新增一条数据,如果key存在,则添加到数据的末尾
formData.get('name') ---------------------- 获取数据,获取key=name的第一个值
formData.getAll('name') -------------------- 获取key=name的所有值
formData.set('name', 'zhang') -------------- 修改数据
formData.has('name') ----------------------- 是否存在
formData.delete('name') -------------------- 删除数据
https://segmentfault.com/a/1190000006716454
https://blog.csdn.net/zqian1994/article/details/79635413
https://segmentfault.com/a/1190000012327982
https://segmentfault.com/a/1190000004664783
(2) XMLHttpRequest
XMLHttpRequest对象来发送一个Ajax请求,
XMLHttpRequest()构造函数初始化一个 XMLHttpRequest 对象,必须在所有其他方法被调用前调用构造函数。
- 如何获取response?
xhr.response
和xhr.responseText
和xhr.responseXML
const api = new XMLHttpRequest();
方法:
(1) api.open() -------- 初始化HTTP请求参数(url, http方法等),但并不发送请求!!! 供 send() 方法使用
api.open(method, url, async, username, password)
method参数:是http请求的方法,值包括:GET,POST,HEAD
url参数:请求的地址
async参数:是否异步,默认是true,即异步的发送请求。
false,同步,对send()方法的调用将阻塞,直到响应完全接收
true或者省略,异步,且通常需要调用 onreadystatechange() 方法
(2) api.send() -------- 发送一个http请求,请求参数写在send()方法的参数中
api.send(body)
get请求:参数可以直接写在open()方法中
post请求:参数写在该方法中,即body
-- 注意:body参数的数据类型会影响requestHeader中的 Content-Type 的默认值,如何手动指定则会覆盖默认值
如果data是 Document 类型,同时也是HTML Document类型,
则content-type默认值为text/html;charset=UTF-8;否则为application/xml;charset=UTF-8;
如果data是 DOMString 类型,content-type默认值为text/plain;charset=UTF-8;
如果data是 FormData 类型,content-type默认值为multipart/form-data; boundary=[xxx]
如果data是其他类型,则不会设置content-type的默认值
(3) api.setRequestHeader() -------- 指定一个http请求的头部,只有在readyState 为 1 的时候才能调用
api.setRequestHeader('name', 'value')
name参数:头部名称
value参数:头部的值
注意: setRequestHeader()方法可以多次调用,最终的值不是覆盖override而是追加append
注意: setRequestHeader()方法只有在readyState为1时才能调用,即open()方法之后,send()方法之前
(4) api.getResponseHeader() -------- 返回指定的 HTTP 响应头部的值
(5) api.abort() -------- 取消当前响应,关闭连接并且结束任何未决的网络活动
api.abort()将readystate重置为0
应用:如果请求用了太长时间,而且响应不再必要的时候,可以调用这个方法。
abort:是中止的意思
(6) api.onreadystatechange() -------- 在 readyState 状态改变时触发
api.onreadystatechage() :当 readyState 为 3 时,它也可能调用多次。
注意:onreadystatechange()所有字符都是小写,但readyState又是驼峰写法
readyState状态:
0 UNSENT ---- xhr对象成功构造,open()方法未被调用
1 OPENED ---- open()被调用,send()还未被调用,setRequestHeader()可以被调用
2 HEADERS_RECEIVED ---- send()方法已经被调用, 响应头和响应状态已经返回
3 LOADING ---- 响应体(response entity body)正在下载中,此状态下通过xhr.response可能已经有了响应数据
4 DONE ---- 整个数据传输过程结束,不管本次请求是成功还是失败
(7)api.onload -------- 请求成功时触发,此时readyState为4
重要:所有请求成功的回调:
1.除了在api.onreadystatechange指定的回调函数的readyState===4时取值
2.也可以在api.onload事件中取值,如
api.onload = function () {
//如果请求成功
if(api.status == 200){
//do successCallback
}
}
3.注意判断api.status===200是有坑的,因为成功时返回的状态码不止有200,下面的写法更靠谱
靠谱的写法:当http状态码为2xx或304时才认为成功
api.onload = function () {
//如果请求成功
if((api.status >= 200 && api.status < 300) || api.status == 304){
//do successCallback
}
}
(8)api.timeout --------- timeout属性用来设置过期时间
问题1:请求的开始时间怎么确定?是api.onloadstart事件触发的时候,也就是api.send()调用的时候
解析:因为api.open()只是创建了链接,当并没有真正传输数据,只有调用api.send()时才真正开始传输
问题2:什么时候是请求结束?
解析:api.loadend事件触发时结束
(9)
api.onprogress 下载进度信息
api.upload.onprogress 上传进度信息
api.upload.onprogress = function(e) {
if ( e.lengthComputable ) {
const present = e.loaded / e.total * 100;
}
}
-----------------------------------------------------------------------------------------------
1.
问题1:如何获取response
提供三个属性来获取response:( api.response ) 和 ( api.responseText ) 和 ( responseXML )
api.responseText --- api.responseType='text'、''、不设置时,xhr对象上才有此属性,此时才能调用
api.response --- responseType为""或"text"时,值为"";responseType为其他值时,值为 null
2.
问题2:api.responseType有哪些类型
api.responseType类型有:text, document, json, blob, arrayBuffer
get请求
go() {
console.log('1111111111');
const api = new XMLHttpRequest();
api.open('GET', ----- 初始http请求参数,请求方式,url, 是否异步
'http://image.baidu.com/channel/listjson?pn=0&rn=30&tag1=明星&tag2=全部&ie=utf8', true);
api.responseType = 'text'; ------ 文本格式的响应
api.timeout = 5000; ---- 请求过期时间
api.setRequestHeader('Content-type', 'application/json'); ----- 必须在open()后,send()前设置
api.onreadystatechange = function() { ------ readyState改变时触发
if ( api.readyState === 4 && this.status === 200) { ---- this指的是api实例
console.log(JSON.parse(this.responseText)) ------ this.response也能拿到同样的数据
}
}
// 除了在api.onreadystatechange指指定的会调中判断readyState===4,也可以直接在onload中触发
// 两种方法都可以
// 只判断200状态码不完善,应该判断 2xx 或者 304 则请求成功
api.onload = function() {
if ( api.status >= 200 && api.status < 300 || api.status === 304 ) {
console.log(JSON.parse(api.responseText), 'onload在请求成功时触发');
}
}
api.send(); ---- 发送数据
}
http://www.ruanyifeng.com/blog/2012/09/xmlhttprequest_level_2.html 大家
https://segmentfault.com/a/1190000004322487重要
http://www.w3school.com.cn/xmldom/dom_http.asp
https://blog.csdn.net/harryhare/article/details/80778066四种 post 请求的写法
https://www.cnblogs.com/wgbs25673578/p/5056300.html 可以
(3) 图片上传
- type属性:规定input元素的类型
- multiple属性:上传多张图片或多个文件
- accept属性:允许上传的文件类型
--- image/*:上传所有图片类型,注意会影响速度
--- image/gif,image/jpeg,image/jpg,image/png ---- 直接写出来则不会影响速度 - 修改默认样式,自带的样式很丑,且后面带有未选择任何文件的文字,选中后的文件名
思路:隐藏,使用自定义的button通过$refs去触发文件上传,实现自定义显示
- 上传同一个文件,不会触发change事件,即使该文件做过修改
思路:文件上传之后,处理完文件,将的value设置为null,这样下次即使上传的是同一个文件,仍然会触发change事件
- display: none不占文档空间
- visibility: hidden占据空间
图片上传
+
{{item}}
https://segmentfault.com/a/1190000013799753
https://www.cnblogs.com/fozero/p/8835628.html
https://www.jianshu.com/p/c619b81e8f04
(4) 上传前预览图片
读取本地图片,有两种方法:FileReader 和 URL.createObjectURL
-----URL.createObjectURL性能更好
objectURL = URL.createObjectURL(blob)
- blob:是用来创建 URL 的 ( File对象 ) 或 ( Blob对象 )
//获取本地图片地址
getObjectURL(file) { ---------------- 传入file对象
let url = null;
if (window.createObjectURL != undefined) { ---------- 判断不同浏览器类型
// basic
url = window.createObjectURL(file);
} else if (window.webkitURL != undefined) {
// webkit or chrome
url = window.webkitURL.createObjectURL(file);
} else if (window.URL != undefined) {
// mozilla(firefox)
url = window.URL.createObjectURL(file);
}
return url;
}
完整案例:
{{ msg }}
上传图片
{{errMessage}}
{{item.name}}
https://blog.csdn.net/weixin_38023551/article/details/78318532
https://developer.mozilla.org/zh-CN/docs/Web/API/URL/createObjectURL
https://www.cnblogs.com/stephenykk/p/3558887.html
(5) 上传进度信息和下载进度信息
onprogress事件用来返回进度信息
- xhr.onprogress = updateProgress; -------------------------- 下载进度信息
- xhr.upload.onprogress = updateProgress; ---------------- 上传进度信息
api.upload.onprogress=function (e){
if(e.lengthComputable){
var precent=100 * e.loaded/e.total;
console.log(precent);
}
}
解析:
1. e.total -------------------- 传输的总字节
2. e.loaded ------------------- 已经传输的字节
3. e.lengthComputable --------- 指定上传总数居的大小(上传文件总大小已知)
4. e.transferSpeed ------------ 传输速度
5. e.timeRemaining ------------ 剩余时间
(5) blob对象
blob对象表示一个不可变的,原始数据的类文件对象。File接口基于Blob,Blob对象可以看作是存放二进制数据的容器
##### new Blob(dataArr:Array, opt:{type:string});
第一个参数:是要添加到Bolb对象的数据数组,注意:是一个数组
第二个参数:配置对象
- 构造函数:Blob()
- 返回一个新创建的 Blob 对象,其内容由参数中给定的数组串联组成
- 属性:
Blob.size:blob中包含数据的大小
Blob.type:一个字符串,表明该Blob的对象所包含数据MIME类型
http://www.cnblogs.com/hhhyaaon/p/5928152.html 应用场景( 分片上传 )
https://blog.csdn.net/qq_42842709/article/details/82500029
(6) new Image() ----- 用于生成 HTMLImageElement 实例
参数:new Image(width, height)
---- 接受两个参数,分别表示宽度和高度
属性:src,currentSrc,alt,srcset,sizes
注意:用js生成的img实例,并不在文档中,需要手动插入
事件:
- onload:图像加载完成,会触发onload属性指定的回调函数
- onerr0r:图像加载完成,同时也会触发onerror属性指定的回调函数
注意事项:
生成的image一定要手动插入到文档,onload和onerror的回调都要指定
mounted() {
const limg = require('../images/1.jpg');
const img = new Image(200, 200); ------------- 参数分别是 width 和 height
img.src = limg; ---------------- 除了src,还有currentSrc表示当前src,因为src可以动态指定
img.onload = function() {
console.log('加载完成');
document.body.appendChild(img); -------------- 插入文档
}
img.onerror = function() {
console.log('错误')
}
}
完整示例
{{ msg }}
上传图片
{{errMessage}}
上传进度:{{persent}}
{{item.name}}
复习: 2019/3/22
Document
上传