在 Web 开发中,文件上传是一个非常常见的需求。本文将介绍如何使用 Vue实现一个简单的自定义文件上传组件,并详细解释其实现原理和潜在的扩展方向。
概述
该组件实现了基本的文件上传功能,用户可以通过点击按钮选择文件并上传到服务器。此外,还提供了删除已上传文件的功能。尽管功能相对简单,但通过一些改进可以满足更多实际需求。
已实现功能:
- 文件类型限制
- 文件大小限制
- 单文件上传
- 上传后的文件显示与删除
待完善功能:
- 多文件上传支持
- 文件预览(如图片、PDF等)
- 上传按钮样式自定义
核心代码
模板结构 <template>
<template>
<div class="upload-box">
<!-- 显示上传按钮和描述 -->
<div v-show="!hideUpload">
<div class="upload-wrapper">
<div class="display-flex align-center">
<img class="plus-icon" :src="require('../../assets/plus.png')" alt="">
<span class="fileupload-text">添加</span>
</div>
<div class="file-desc">{{ text }}</div>
</div>
<!-- 隐藏的文件输入框 -->
<input
type="file"
style="display:none"
ref="file"
@click="e => {e.target.value = '';}"
:accept="accept"
@change="getFileData"/>
</div>
<!-- 显示已上传文件信息 -->
<div class="file-show" v-show="hideUpload">
<div class="file-text">
<img src="../../assets/file-icon.png" alt="">
<span>{{ fileName }}</span>
</div>
<!-- 删除按钮 -->
<img src="../../assets/clear-file.png" alt="" class="clear-icon" @click.stop="reUpload">
</div>
</div>
</template>
v-show="!hideUpload":控制是否显示上传按钮区域。v-show="hideUpload":控制是否显示已上传文件的信息。
<script>
<script>
import { upLoad } from '../../utils/api/...'; // 假设这是你的上传接口
export default {
name: "index",
props: {
text: { // 上传按钮文本
type: String,
default: "文件上传"
},
accept: { // 允许的文件类型
type: String,
default: ".doc,.docx,.pdf,.jpg,.jpeg,.gif,.png,.mp3,.mp4,.avi,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/pdf"
},
applyType: { // 文件所属应用类型
type: String,
default: "application"
},
maxSize: { // 文件大小限制,默认2MB
type: Number,
default: 2
},
limit: { // 文件数量限制
type: Number,
default: 1
}
},
data () {
return {
docType: { // 文档类型检查
'.doc': 'application/msword',
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'pdf': 'application/pdf'
},
hideUpload: false, // 控制UI显示状态
fileName: '' // 保存文件名
}
},
methods: {
clickUpload () {
if (this.hideUpload === true) {
// 如果已经上传了文件,则不触发新的上传
} else {
this.$refs.file.dispatchEvent(new MouseEvent("click")); // 触发文件选择对话框
}
},
getFileData () {
const inputFile = this.$refs.file.files[0]; // 获取选择的文件
if (inputFile) {
// 检查文件类型和大小
if (!this.checkFileType(inputFile)) {
this.$toast('请上传正确的文件类型');
return;
}
if (inputFile.size > this.maxSize * 1024 * 1024) {
this.$toast('文件大小已超出上传限制');
return;
}
this.setUpload(inputFile.name, inputFile);
} else {
this.$toast('文件上传失败,请重试!');
}
},
setUpload (name, file) {
const formData = new FormData();
formData.set("fileName", name);
formData.set("file", file);
upLoad(formData).then(res => {
if (res.code === 200) {
this.hideUpload = true;
this.fileName = name; // 更新文件名显示
this.$emit('getFile', res.data); // 向父组件传递数据
} else {
this.$toast('上传失败,请重试!');
}
}).catch(err => {
this.$toast('上传失败,请重试!');
console.error(err);
});
},
reUpload () {
this.$refs.file.value = null;
this.hideUpload = false;
this.$emit('getFile', {
fileName: null,
url: null
});
},
checkFileType (file) {
const accept = this.accept.split(',') || [];
const fileType = '.' + file.type.split('/')[1];
return accept.includes(fileType) || accept.includes(file.type);
}
}
}
</script>
<style scoped>
<style lang="scss" scoped>
.upload-box{
margin: 40px auto;
}
.upload-wrapper{
display: flex;
flex-direction: column;
align-items: center;
.file-desc{
max-width: 354px;
color: #A2A2A2;
font-size: 26px;
text-align: center;
}
}
.plus-icon{
width: 42px;
height: 42px;
margin-right: 17px;
}
.fileupload-text{
font-size: 28px;
color: #797979;
}
.file-show{
margin: 0 20px;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
}
.file-text{
font-size: 26px;
font-family: Microsoft YaHei, Microsoft YaHei-Regular;
font-weight: 400;
color: #797979;
letter-spacing: 1.56px;
margin-left: 25px;
}
.clear-icon{
margin-left: 40px;
}
</style>
功能扩展建议
1. 多文件上传
- 修改
limit属性以允许上传多个文件。 - 在
methods.getFileData中处理多个文件的选择。
2. 文件预览
- 对于图片、PDF等文件类型,可以在上传后显示缩略图或直接嵌入页面进行预览。
3. 上传按钮样式自定义
- 提供更多的
props参数来允许用户自定义按钮的颜色、字体等样式。
总结
这个自定义文件上传组件虽然功能基础,但通过一些简单的修改就能适应更多的应用场景。
自定义上传组件:文件上传与管理简易实现

本文介绍了一个简单的自定义文件上传功能组件,支持单文件上传,包括文件类型检查、大小限制及上传操作。组件尚未实现多文件上传和预览,按钮样式定制也暂未完成。

1294

被折叠的 条评论
为什么被折叠?



