2018-10-26 Element Ui upload 圖片寬高的校驗(yàn)

在調(diào)試圖片限制寬高時(shí) 出現(xiàn)了很多的問題 一開始我直接百度google, 發(fā)現(xiàn)都沒有這個(gè)問題.感覺這應(yīng)該是很常見的需求, element內(nèi)部沒有實(shí)現(xiàn), 也許是很簡單?網(wǎng)上都沒有此類問題.
到GitHub的issue里看, 確實(shí)有類似的問題, 但沒有系統(tǒng)的解決方法.一開始,我的思路就是按照常規(guī)的校驗(yàn)方法去校驗(yàn), 由于js是沒有讀取圖片權(quán)限的, 在這里我使用了URL對象的URL.createObjectURL(file)方法, 其中包含一個(gè)表示參數(shù)中給出的對象的URL, 這個(gè)URL的生命周期和創(chuàng)建它的窗口中的document 綁定, 可以用于在瀏覽器上預(yù)覽本地圖片或者視頻.
但是既然是通過url讀取寬高就牽扯到圖片是否加載完畢的問題, 雖然是在本地創(chuàng)建一個(gè)圖片對象, 但創(chuàng)建還是有延遲問題.


image.png

打印出來可以看到是有延遲問題的

解決了文件讀取問題后我就能拿到圖片真實(shí)寬高了, 經(jīng)過反復(fù)的debug 我發(fā)現(xiàn)img.onload并沒有走, isSize也一直是false, 看來這種邯鄲學(xué)步的方法顯然行不通, 想到onload是異步的, 來不及走就return結(jié)束了這個(gè)方法, 其實(shí)最省事的辦法, 就是給圖片判斷加上1秒的延遲, 但這種做法顯然是在自掘墳?zāi)?所以還是需要拿到文件真實(shí)的加載完成狀態(tài), 所以想法異步操作一下, 讓onload之后再執(zhí)行isSize的判斷以及return, 于是我就增加回調(diào)函數(shù)使onload先執(zhí)行, 然后對isSize有賦值操作.代碼如下:


img

之后isSize確實(shí)被重新賦值, 也有了正確的提示, 但只是一閃而過, 并成功的上傳了???
雖然有錯(cuò)誤提示 但還是上傳了
反復(fù)撓頭.jpg

一步步的開始debug了, 發(fā)現(xiàn)最后還是可以回到return的, 但是不知道原因, 接著又開始google了, 發(fā)現(xiàn)我的思路是錯(cuò)的.我發(fā)現(xiàn)beforeAvatarUpload其實(shí)是返回一個(gè)Promise
我在查看了一篇文章后, 發(fā)現(xiàn)Element Ui的upload人家內(nèi)部確實(shí)是想要一個(gè)promise, 直接給isSize一個(gè)boolean值return出去其實(shí)是沒有任何作用的, 這就解釋了為什么可以彈出錯(cuò)誤信息卻可以成功上傳了, 這個(gè)是開始的實(shí)現(xiàn)方法
再后來我通過查看源碼之后發(fā)現(xiàn)this.beforeUpload是一個(gè)真正的promise, 也就是說必須返回一個(gè)promise, 簡單的boolean值是沒用的, 因?yàn)镋lement組件內(nèi)部還有很多的對promise的實(shí)現(xiàn).
這下清楚了一點(diǎn), 就有了最終的方法, 經(jīng)過多次測試終于可以了.

beforeAvatarUpload(file) {
        this.filterType = []
        if (this.pType) { // 判斷父組件傳過來的可上傳圖片類型
          const typeArr = this.pType
          for (const i in typeArr) {
            this.filterType.push(this.imgType[typeArr[i]])
          }
        } else { // 如果沒有直接賦值為默認(rèn)
          this.filterType = this.imgType
        }
        let typeFlag = false
        for (const o in this.filterType) {
          if (this.filterType[o] === file.type) {
            typeFlag = true
          }
        }
        const isLt1M = file.size / 1024 / 1024 < 1
        if (!typeFlag) {
          this.$message.error('上傳圖片只能是 ' + this.filterType + ' 格式!')
        }
        if (!isLt1M) {
          this.$message.error('上傳圖片大小不超過 1MB')
        }
        const _width = 210
        const _height = 100
        const isSize = new Promise(function(resolve, reject) {
          const _url = URL.createObjectURL(file)
          const img = new Image()
          if (1) { // 是否判斷寬高
            img.onload = function() {
              const valid = img.width === _width
              valid ? resolve() : reject()
            }
          } else {
            resolve()
          }
          img.src = _url
        }).then(() => {
          return true
        }, () => {
          this.$message.error('上傳的尺寸必須是寬:' + _width + 'px 高:' + _height + 'px')
          return Promise.reject()
        })
        return typeFlag && isLt1M && isSize
      }

當(dāng)然 我這里寬高為固定的寬高, 在實(shí)際代碼中可以是子組件傳過來的, 如果沒有傳值也可以不限制, 判斷那里我還沒有寫.這個(gè)功能看似很簡單很簡單, 但是其實(shí)牽扯到promise異步調(diào)用返回值, 由于以前異步基本都用在ajax請求, 并沒有在別的地方用過, 所以花些時(shí)間學(xué)習(xí)了一下.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容