element ui实现手动上传文件,且只能上传单个文件,并能覆盖上传。
element ui提供了成熟的组件场景,但实际工作中难免会遇到认(sha)真(diao)的产品。比如,最近遇到的,要求实现手动上传特定格式文件(用户点击“上传文件”按钮,确定之后,只是单纯选择了文件,点击页面上的“提交”按钮才上传),并展示用户选择的文件名称,且只能选择一个文件,如果用户选择第2,3,4...等文件,要求后者覆盖前者,即用户看到的总是最新选择的文件。
OK,需求合理,但是,查了查API,呃。。。貌似不太好完美实现。
查源码,改样式。完美奉上解决方案。
一,实际应用场景
实现手动上传特定格式的文件,展示所选文件名称,且能实现覆盖上传。
二,分析
1, 解决手动上传问题
官网API(https://element.eleme.cn/#/zh-CN/component/upload),给出“手动上传”,只需要在Upload组件添加 属性 :auto-upload="false" ,然后调用 this.$refs.upload.submit(); 方法即可。
2,解决特定格式文件问题
这块,也有例子,对于本项目,要求添加csv格式, 所以,Upload组件添加 属性 accept=".csv"
3,最麻烦的是上传限制问题
首先想到官网API里的 limit属性, Upload组件添加属性 :limit="1",但是这样,无聊怎么选择文件,页面上展示的始终是第一次选择的文件,这效果和我想的大相径庭。
“单身限制了你的想象力”
继续翻,看到file-list属性,保存的是用户选择的文件数组。
想通过on-change方法,改变file-list里选择的文件列表,只保留最后一项。逻辑上来说行得通。
代码如下:
模板代码(已精简):
<template> <div> <el-upload class="upload-demo" ref="upload" // 注意1 accept=".csv" // 注意2 :file-list="fileList" // 注意3 :on-change="handleChange" // 注意4 :action="uploadUrl" :show-file-list="true" :on-success="onSuccess" :on-error="onError" :auto-upload="false" // 注意5 > <el-button type="primary" slot="trigger">选取文件</el-button> </el-upload> <el-button type="primary" @click="handleSubmit">提交</el-button> </div> </template>
script代码:
<script> export default { name: 'Upload', data() { fileList: [], uploadUrl: '', }, methods: { onSuccess(res) { this.$alert(res.data, '提示', { confirmButtonText: '确定', callback: action => { console.log("上传成功") }, }) }, onError(res) { this.$alert('创建失败', '提示', { confirmButtonText: '确定', callback: action => { console.log("上传失败") }, }) }, handleChange(file, fileList) { if (fileList.length > 0) { this.form.fileList = [fileList[fileList.length - 1]] // 这一步,是 展示最后一次选择的csv文件 } }, submit() {
this.uploadUrl = '/upload' // 这里,读者换成实际项目中的上传接口 this.$nextTick(() => { this.$refs.upload.submit() }) }, }, } </script>
到这里,基本功能上实现了目标场景,但是有一个样式问题,因为是认为改变file-list,取最后一项,因此,用户选择第二个文件后,从第一个文件到第二个文件,有动态切换的效果,这不是我想要的,我想要的是 用户点击“上传文件”,本地电脑 选择文件,点击“确定”,页面上直接展示所选文件,不要动态切换。
鼓捣很久(省略很多字),翻看element upload组件的css源码。
去掉这一部分动画,完美解决。
css代码如下:
<style lang="scss" scoped> .upload-demo { display: flex; } /deep/ .el-list-enter-active, /deep/ .el-list-leave-active { transition: none; } /deep/ .el-list-enter, /deep/ .el-list-leave-active { opacity: 0; } /deep/ .el-upload-list { height: 40px; } </style>
至于css中的 /deep/ 是干嘛的,其实是修改elementui等第三方组件内部样式,做的渗透。如果不用scss, 可以使用 >>> 符号来修改第三方组件内部样式。
三,总结
“什么都不懂的时候,我曾拥有全部。”
本文思路,从 踩过的坑 到解决问题,耗时许久,如需转载,请标明出处,感谢配合。
还是同样的ps,每次用element ui 都会有一些感触,
苦笑。