element-ui Upload 上传文件

6,851 阅读2分钟

element-ui Upload 上传文件

需求描述:如图所示,upload 只是用来选择文件,在点击提交的时候再和其他的数据统一上传,并且要限制该文件只能上传一个,为用户最后选择的那个文件。

upload.png

  • 不使用 action 属性 上传 官方文档 文档中描述到: action:是必选参数,上传的地址; http-request: 覆盖默认的上传行为,可以自定义上传的实现, 使用该属性的时候设置action 的属性值为#

  • 只能上传单个文件,并能覆盖上传 官网 API 里有一个属性,limit(number 类型),指的是最大允许上传个数,我添加其属性值为 1,(:limit='1'),但是这样,无论怎样选择,页面上展示的始终是用户第一次选择的文件,这个效果...emmm 和我们想要的不一样呢 继续看官方文档,有个 file-list 属性,指的是上传文件的列表,🉑 ️ 通过文件状态改变时的钩子 on-change 方法,改变 file-list 的文件列表,一直保留最后一项。 file-list.png

模板代码

 <el-upload
        class="upload-demo"
        drag
        action="#"
        :multiple="false"
        :show-file-list="true"
        :http-request="uploadHttpRequest"
        :file-list="fileList"
        :on-change="handleUploadChange"
        :before-upload="beforeUpload"
    >
    <i class="el-icon-upload"></i>
    <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>

js 代码

// 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。
   data() {
       return {
           // 上传文件的列表
           fileList: [],
       }
   },
   methods: {
       beforeUpload(file) {
        const fileType = file.name.substring(file.name.lastIndexOf('.'))
        if (fileType.toLowerCase() != '.txt' && fileType.toLowerCase() != '.xml') {
            this.$message.error('文件必须为.txt或.xml类型')
            this.fileList = []
            return false
        }
        },
        // 覆盖element的默认上传文件
        uploadHttpRequest(data) {
            let reader = new FileReader()
            let that = this
            reader.readAsText(data.file)
            reader.onload = function() {
                that.formData.mmiapXml = this.result
            }
        },
        // 限制文件上传的个数只有一个,获取上传列表的最后一个
        handleUploadChange(file, fileList) {
            if (fileList.length > 0) {
                this.fileList = [fileList[fileList.length - 1]] // 这一步,是 展示最后一次选择的文件
            }
        },
   }

目前已经实现了基本需求,样式上有点小瑕疵,因为我们改变是文件列表,已经选择过文件,再次选择文件之后,从第一个文件到第二个文件,有动态切换的效果, 这个特效我们不需要。在 elment 的 upload 源码中,有这样一个动画:

.el-list-enter-active, .el-list-leave-active {
    -webkit-transition: all 1s;
    -o-transition: all 1s;
    transition: all 1s;
}

我们设置 transition 为 none 去掉这一部分动画就可以了,当 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素,如果你希望 scoped 样式中的一个选择器能够作用得“更深”,可以使用深度作用选择器 >>> , 但如果是 sass/less 的话可能无法识别,这时候需要使用 /deep/ 选择器。

<style lang="less" scoped>

/deep/ .el-list-enter-active,
/deep/ .el-list-leave-active {
    transition: none;
}

/deep/ .el-list-enter,
/deep/ .el-list-leave-active {
    opacity: 0;
}
</style>