封装一个上传文件的组件,如下:
这里写图片描述
使用<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);

        }
Logo

前往低代码交流专区

更多推荐