首頁  >  文章  >  web前端  >  JavaScript拖曳上傳功能的實作及原理介紹

JavaScript拖曳上傳功能的實作及原理介紹

不言
不言轉載
2019-02-19 15:55:454074瀏覽

這篇文章帶給大家的內容是關於JavaScript拖曳上傳功能的實現及原理介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

最近,小明遇到這樣一種情況:在網頁中上傳文件時偶爾頁面會崩潰。小明仔細測試了這種情況,發現之前用的一個文件上傳組件有一點缺陷,於是,小明決定自己手寫一個,樣式如下:

JavaScript拖曳上傳功能的實作及原理介紹

JavaScript拖曳上傳功能的實作及原理介紹

圖一是沒有上傳檔案時的樣式,圖二為上傳檔案後的樣式。虛線部分為放置區域,先來看程式碼:

html部分

<div>
    <div>
      <div>
        <div>{{ fileName }}</div>
        <div>
          <span>将文件拖拽至此,或</span>
          <label>点此上传</label>
        </div>
      </div>
    </div>

    <div>
      <input>
      <label>选择文件</label>

      <button>提交</button>
    </div>
  </div>

css部分

    * {
      font-size: 14px;
    }
    .drag-area {
      height: 200px;
      width: 300px;
      border: dashed 1px gray;
      margin-bottom: 10px;
      color: #777;
    }
    .uploader-tips {
      text-align: center;
      height: 200px;
      line-height: 200px;
    }
    .file-name {
      text-align: center;
      height: 200px;
      line-height: 200px;
    }

js部分

    new Vue({
      el: '#app',
      data () {
        return {
          fileName: '',
          batchFile: '',
          MAX_FILE_SIZE: 10 * 1000 * 1000
        }
      },
      methods: {
        // 点击上传
        chooseUploadFile (e) {
          const file = e.target.files.item(0)

          if (!file) return
          if (file.size > this.MAX_FILE_SIZE) {
            return alert('文件大小不能超过10M')
          }

          this.batchFile = file
          this.fileName = file.name

          // 清空,防止上传后再上传没有反应
          e.target.value = ''
        },
        // 拖拽上传
        fileDragover (e) {
          e.preventDefault()
        },
        fileDrop (e) {
          e.preventDefault()
          const file = e.dataTransfer.files[0] // 获取到第一个上传的文件对象

          if (!file) return
          if (file.size > this.MAX_FILE_SIZE) {
            return alert('文件大小不能超过10M')
          }

          this.batchFile = file
          this.fileName = file.name
        },
        // 提交
        uploadOk () {
          if (this.batchFile === '') {
            return alert('请选择要上传的文件')
          }

          let data = new FormData()
          data.append('upfile', this.batchFile)

          // ajax
        }
      }
    })

核心原理說明

  • #dragover和drop事件

##第一個要說的是拖曳中的這兩個事件,因為這兩個事件撐起了拖曳上傳的核心功能。

對於拖曳這個動作而言,有二個核心概念,一個是
拖曳元素,另一個是放置目標。這裡,我只講放置目標上的事件,對於拖曳元素的事件,請自行查閱。

那對於放置目標,它有什麼事件呢?如下:

當某個元素被拖曳到一個有效的放置目標上(如上例中虛線區域)時,下列事件會依序發生:
(1) dragenter
(2) dragover
(3) dragleave 或drop
只要有元素被拖曳到放置目標上,就會觸發dragenter 事件(類似mouseover 事件)。緊接在後的是 dragover 事件,而且在被拖曳的元素還在放置目標的範圍內移動時,就會持續觸發該事件。如果元素被拖曳了放置目標,dragover 事件不再發生,但會觸發 dragleave 事件(類似 mouseout事件)。如果元素被放到了放置目標中,則會觸發 drop 事件而不是 dragleave 事件。

對於本例來說,我們只需要關注dragover和drop事件。但drop事件有點調皮,你想監聽它,還得進行一些處理,因為預設情況下,元素是不允許放置的,在拖曳元素經過某些無效放置目標時,可以看到一種特殊的遊標(圓環中有一條反斜線),表示不能放置。如下:

JavaScript拖曳上傳功能的實作及原理介紹

如果拖曳元素經過不允許放置的元素,那麼無論使用者如何操作,都不會發生 drop 事件。那怎麼辦呢?

我們可以重寫 dragover 事件的預設行為,如上例程式碼中的e.preventDefault()。
細心的同學可能要問了,那drop事件中也有e.preventDefault(),去掉行不行呢?大家可以自行試下。

  • dataTransfer 物件

可能這個物件看著有些陌生,但是它的作用可不小。例如,你拖曳一個圖片到目標區域,那目標區域怎麼取得這個圖片的資訊呢?就靠它!它是事件物件的屬性,用於從被拖曳元素向放置目標傳遞字串格式的資料。在本例中,我們可以透過它來取得拖曳中的檔案資訊。

  • input的change事件

這個事件其實有坑的,它有這樣一個特性,就是:上傳同一個文件,並不會觸發change事件,即使該文件內容做過修改。

細思極恐!例如,使用者要上傳一個文檔,但是拖曳到虛線區域後發現文檔內容還需要修改下,他改完後再拖曳該文檔,再提交到伺服器,那麼他上傳到伺服器的文檔內容卻是未修改之前的!
所以,我們需要程式碼e.target.value = ''來進行重置處理,這樣,每次上傳檔案都會觸發change事件。


以上是JavaScript拖曳上傳功能的實作及原理介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除