『设计』ES6原生实战Uploader工具类(从设计到实现)( 三 )

到这里其实还没完善 , 因为loadFiles可以用于别的场景下添加文件 , 我们再增加些许类型判断代码 。
class Uploader {// ...loadFiles (files) {if (!files) return false;+const type = Object.prototype.toString.call(files)+if (type === '[object FileList]') {+files = [].slice.call(files)+} else if (type === '[object Object]' || type === '[object File]') {+files = [files]+}if (this.limit !== -1 &&files.length &&files.length + this.uploadFiles.length > this.limit) {this._callHook('exceed', files);return false;}+this.uploadFiles = this.uploadFiles.concat(files.map(file => {+if (file.uid && file.rawFile) {+return file+} else {return {uid: uid++,rawFile: file,fileName: file.name,size: file.size,status: 'ready'}}}))this._callHook('change', this.uploadFiles);this.setting.autoUpload && this.upload()return true}}上传文件列表 - upload 【『设计』ES6原生实战Uploader工具类(从设计到实现)】这里可根据传进来的参数 , 判断是上传当前列表 , 还是单独重传一个 , 建议是每一个文件单独走一次接口(有助于失败时的文件追踪) 。
upload (file) {if (!this.uploadFiles.length && !file) return;if (file) {const target = this.uploadFiles.find(item => item.uid === file.uid || item.uid === file)target && target.status !== 'success' && this._post(target)} else {this.uploadFiles.forEach(file => {file.status === 'ready' && this._post(file)})}} 当中涉及到的_post函数 , 我们往下再单独实现 。
交互方法 这里都是些供给外部操作的方法 , 实现比较简单就直接上代码了 。
class Uploader {// ...chooseFile () {// 每次都需要清空value,否则同一文件不触发changethis.input.valuehttp://news.hoteastday.com/a/= ''this.input.click()}removeFile (file) {const id = file.id || fileconst index = this.uploadFiles.findIndex(item => item.id === id)if (index > -1) {this.uploadFiles.splice(index, 1)this._callHook('change', this.uploadFiles);}}clear () {this.uploadFiles = []this._callHook('change', this.uploadFiles);}destroy () {this.input.removeEventHandler('change', this.changeHandler)this.setting.wrapper.removeChild(this.input)}// ...} 有一点要注意的是 , 主动调用chooseFile , 需要在用户交互之下才会触发选择文件框 , 就是说要在某个按钮点击事件回调里 , 进行调用chooseFile 。 否则会出现以下这样的提示:
『设计』ES6原生实战Uploader工具类(从设计到实现)
本文插图
写到这里 , 我们可以根据已有代码尝试一下 , 打印upload时的内部uploadList , 结果正确 。
『设计』ES6原生实战Uploader工具类(从设计到实现)
本文插图
发起请求 - _post 这个是比较关键的函数 , 我们用原生XHR实现 , 因为fetch并不支持progress事件 。 简单描述下要做的事:

  1. 构建FormData , 将文件与配置中的data进行添加 。
  2. 构建xhr , 设置配置中的header、withCredentials , 配置相关事件