內(nèi)容簡(jiǎn)介
記錄了一次通過(guò)閱讀Element-UI源碼,利用hack手段,進(jìn)入el-upload組件特定鉤子的方法。
為什么要這么做?
Element-UI是一款優(yōu)秀的開(kāi)源項(xiàng)目,但它也無(wú)法滿足所有的用戶場(chǎng)景。
當(dāng)無(wú)法滿足的時(shí)候,我們可以選擇:
- 自己寫個(gè)組件
- 對(duì)element的組件進(jìn)行改造
- hack方式
如果有把握,方法3絕對(duì)是代價(jià)最小,而且最穩(wěn)妥的。
現(xiàn)狀是什么?
Element-UI的el-upload對(duì)文件的處理是按單文件進(jìn)行的,無(wú)論你一次選中多少個(gè)文件,它都會(huì)對(duì)文件列表進(jìn)行遍歷,依次上傳。
每一個(gè)文件都會(huì)走一遍完整的生命周期。
我的期望是什么?
因?yàn)闃I(yè)務(wù)需要,我需要支持一次選擇/拖拽多個(gè)文件,并將多個(gè)文件封裝到一個(gè)Formdata中,使用一次http(s)請(qǐng)求,完成多個(gè)文件的上傳。
當(dāng)前組件為何無(wú)法滿足
上面的現(xiàn)狀描述了el-upload的實(shí)現(xiàn)機(jī)制,那就決定了我無(wú)法在一個(gè)方法中,獲得全部數(shù)據(jù)列表。(也不是完全不可以,在文件列表的最后一次觸發(fā)是,fileList即為全部數(shù)據(jù)列表,但無(wú)法確認(rèn)什么時(shí)候是最后一次)
怎么辦?先讀讀源碼吧。
以下是Element-UI中,upload組件的相關(guān)業(yè)務(wù)代碼:
uploadFiles(files) {
if (this.limit && this.fileList.length + files.length > this.limit) {
this.onExceed && this.onExceed(files, this.fileList);
return;
}
let postFiles = Array.prototype.slice.call(files);
if (!this.multiple) { postFiles = postFiles.slice(0, 1); }
if (postFiles.length === 0) { return; }
postFiles.forEach(rawFile => {
this.onStart(rawFile);
if (this.autoUpload) this.upload(rawFile);
});
}
可以看到,源碼做了如下處理:當(dāng)一些判斷結(jié)束后,立刻開(kāi)始對(duì)postFiles進(jìn)行forEach,依次處理上傳。
逃票了!
看到這,我很沮喪!Element-UI團(tuán)隊(duì)居然沒(méi)有給我們留鉤子!
不對(duì)!等等!
也不是完全沒(méi)有鉤子,對(duì)吧?
比如說(shuō)上面代碼里的onExceed鉤子,當(dāng)文件上傳數(shù)量超過(guò)限制時(shí),會(huì)直接進(jìn)入該方法。而且?guī)狭巳课募?br>
咦?
怎么樣可以百分百進(jìn)入該方法呢?
this.limit < 0 不就可以了?
解決的思路瞬間清晰:令limit = -1,那么便可以在組件的on-exceed鉤子中,獲取到全部的文件了!