element-ui Upload 上传文件
需求描述:如图所示,upload 只是用来选择文件,在点击提交的时候再和其他的数据统一上传,并且要限制该文件只能上传一个,为用户最后选择的那个文件。
-
不使用 action 属性 上传 官方文档 文档中描述到: action:是必选参数,上传的地址; http-request: 覆盖默认的上传行为,可以自定义上传的实现, 使用该属性的时候设置action 的属性值为#
-
只能上传单个文件,并能覆盖上传 官网 API 里有一个属性,limit(number 类型),指的是最大允许上传个数,我添加其属性值为 1,(:limit='1'),但是这样,无论怎样选择,页面上展示的始终是用户第一次选择的文件,这个效果...emmm 和我们想要的不一样呢 继续看官方文档,有个 file-list 属性,指的是上传文件的列表,🉑 ️ 通过文件状态改变时的钩子 on-change 方法,改变 file-list 的文件列表,一直保留最后一项。
模板代码
<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>