问题:
在实际开发过程中,会遇到上传文件的一些需求。但是使用原生的<input type="file" />
在使用中存在一些问题
- 在未上传文件时,显示”no file choosen”,用户界面不友好,不可配置
- 上传同一个文件,不会触发
change
事件,即使该文件做过修改 - 用户如果在上传过程中点击了“取消”,已经上传的文件会被移除
解决思路
在阅读了一些源码之后,总结了如下的解决方案。有点偷梁换柱的意思:
- 将真正的
<input type="file" />
隐藏,使用自定义的button
通过$refs
去触发文件上传,实现自定义显示 - 文件上传之后,处理完文件,将
<input type="file" />
的value
设置为null,这样下次即使上传的是同一个文件,仍然会触发change
事件 - 使用上述方法,点击取消文件被移除,但是不影响页面展示
具体实现
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="https://unpkg.com/vue"></script>
<title>Vue</title>
</head>
<body>
<div id="app">
<button type="button" @click="click">
<span v-if="fileName">重新上传</span>
<span v-else>上传文件</span>
</button>
<span>{{fileName}}</span>
<input type="file" ref="uploadFile" style="display:none" accept="image/gif, image/jpeg" @change="upload"/>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
fileName: ''
},
methods: {
click () {
// 偷梁换柱,触发文件上传
this.$refs.uploadFile.click();
},
upload (event) {
let files = event.target.files || event.dataTransfer.files;
if (!files.length) {
this.fileName = '';
return;
}
this.fileName = files[0].name;
// 上传之后调用接口...
let params = new FormData();
params.append('file', files[0]);
console.log(params);
this.$refs.uploadFile.value = null; // 移除文件,可以保证上传同样的文件时,也会触发change事件
}
}
})
</script>
</body>
</html>
感想
遇到问题的时候多去看看别人是怎么写的,借鉴一下,解决问题的同时能够学习很多东西。