1. 程式人生 > >在Vue中封裝一個上傳檔案元件

在Vue中封裝一個上傳檔案元件

封裝一個上傳檔案的元件,如下:
這裡寫圖片描述
使用<input type='file'> 來實現檔案上傳,具體操作參照以往JS版的實現
這裡主要說作為一個元件,選中檔案之後,在輸入框中顯示檔名稱,點選Submit將將檔案傳給父元件,再由父元件提價到後臺

<template>
  <div class='filebox'>
    <span class='labeltext'>File Upload:</span>
    <input
     type="text"
     class='inputtext'
     v-model
='filename' >
<input type="button" value='Select File' class='selectbutton'> <input type="file" multiple="multiple" accept=".csv, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" class='selectfile' @change='handleFileChange'
ref='selectfile' >
<button class='submitbutton' :disabled='disabled' @click='handleSubmitFile' >Submit</button> </div> </template> <script> export default { name: 'File', props: { isdisabled: { type: Boolean, required: false
, default: true } }, watch: { isdisabled (val) { this.disabled = true } }, data () { return { filename: '', disabled: this.isdisabled } }, methods: { handleFileChange (e) { // 首先獲取該DOM元素 let inputDOM = this.$refs.selectfile // 通過DOM元素取檔案資料 this.file = inputDOM.files[0] // console.log(this.file) // 獲取檔案的名字 this.filename = this.file.name if (this.filename) { this.disabled = false } else { this.disabled = true } }, handleSubmitFile () { // console.log(this.file) this.$emit('GetFile', this.file) } } }
</script>

佈局就不說了。
首先選中檔案,在輸入框中顯示檔名字,在<input type='file'> 繫結變化事件,並給該DOM元素繫結一個名字


    <input
     ...
     @change='handleFileChange'
     ref='selectfile'
    >

在methods中定義:

  data () {
    return {
      filename: ''
    }
  },
  methods: {
    handleFileChange (e) {
      // 首先獲取該DOM元素
      let inputDOM = this.$refs.selectfile
      // 通過DOM元素取檔案資料
      this.file = inputDOM.files[0]
      // 獲取檔案的名字
      this.filename = this.file.name
    }
  }

ok,顯示檔名稱完成,this.file = inputDOM.files[0] 獲取我們上傳的檔案
我們在點選按鈕觸發往父元件傳送該檔案

    <input
     type="button"
     value='Submit'
     class='submitbutton'
     @click='handleSubmitFile'
    >

在methods中往父元件中傳遞該檔案:

  methods: {
    handleSubmitFile () {
      this.$emit('GetFile', this.file)
    }
  }

在父元件中接收一下:

        <file v-on:GetFile='handleGetFile'></file>
  methods: {
    handleGetFile (file) {
      console.log(file)
    }
  }

在父元件中就可以接收到file了,再繼續下一步往後臺傳值

當沒有選中檔案的時候,按鈕是不可點選的,所以我們給按鈕設定一個是否可以點選的屬性,預設是不可點選的,選中檔案後可以點選。

    handleFileChange (e) {
      // 首先獲取該DOM元素
      let inputDOM = this.$refs.selectfile
      // 通過DOM元素取檔案資料
      this.file = inputDOM.files[0]
      // console.log(this.file)
      // 獲取檔案的名字
      this.filename = this.file.name
      if (this.filename) {
        this.disabled = false
      } else {
        this.disabled = true
      }
    },

當然有時候會遇到一種問題就是按鈕是否可點選是外面父元件來控制做出判斷,所以這個控制按鈕的屬性我們要設定為接收引數,預設不傳的時候,是不顯示的

  props: {
    isdisabled: {
      type: Boolean,
      required: false,
      default: true
    }
  },

當父元件依據判斷條件發現按鈕不能點選(如果是根據條件點選,可以不做操作,一般來講,在這裡想要控制按鈕也是在條件不符合的情況下,按鈕不能點選),所以我們監聽一下父元件的變化,在子元件中設定為不可點選。

  watch: {
    isdisabled (val) {
      this.disabled = true
    }
  },

注意的是,父元件要有變化次才能監聽的到。所以啊。在父元件中

this.submitdisabled = !this.submitdisabled

如果如果條件不符合的話,是用取反的方式,不能寫死,因為下一次要是還不滿足條件,寫死不會起作用,還是那句話,watch一定是資料有變化了才會響應。

附:
檔案的更多操作:

handleFileChange (e) {
            let inputDOM = this.$refs.inputer;
            // 通過DOM取檔案資料
            this.file    = inputDOM.files[0];
            this.errText = '';

            let size = Math.floor(this.file.size / 1024);
            if (size > ...) {
                // 這裡可以加個檔案大小控制
                return false
            }

            // 觸發這個元件物件的input事件
            this.$emit('input', this.file);

            // 這裡就可以獲取到檔案的名字了
            this.fileName = this.file.name;

            // 這裡加個回撥也是可以的
            this.onChange && this.onChange(this.file, inputDOM.value);

        }