Vue开发之封装上传文件组件与用法示例
一、概述
在Vue项目中,我们经常需要使用到上传文件的功能,为了提高代码的可复用性并减少冗余代码,我们可以封装一个通用的上传文件组件。本篇攻略将介绍如何封装上传文件组件以及如何在Vue项目中使用该组件。
二、上传文件组件的封装
- 创建 UploadFile.vue 组件文件,并添加如下代码:
<template>
<div>
<input type="file" :multiple="multiple" @change="upload">
</div>
</template>
<script>
export default {
name: "UploadFile",
props: {
multiple: Boolean, // 是否可多选,默认为false
uploadUrl: String //文件上传接口地址
},
methods: {
upload(e) {
const formData = new FormData();
const files = Array.from(e.target.files);
for (let i = 0; i < files.length; i++) {
formData.append("files", files[i]);
}
// 文件上传接口
fetch(this.uploadUrl, {
method: "POST",
body: formData,
})
.then(function (response) {
return response.json();
})
.then(function (data) {
console.log("文件上传成功");
})
.catch(function (error) {
console.log(error);
});
},
},
};
</script>
- 编写更加灵活的 UploadFile.vue 组件,代码如下:
<template>
<div>
<input type="file" :multiple="multiple" @change="upload">
<slot></slot>
</div>
</template>
<script>
export default {
name: "UploadFile",
props: {
multiple: Boolean,
uploadUrl: String,
fileTypes: {
type: Array,
default: function () {
return [".jpg", ".png", ".gif", ".jpeg", ".bmp"]; //文件类型限制,默认是图片类型
},
},
maxCount: {
type: Number,
default: 1, //默认为最多上传1个文件
},
},
methods: {
beforeUpload: function (file) {
const fileType = file.name.slice(file.name.lastIndexOf("."));
const isFileTypeAllowed = this.fileTypes.includes(fileType);
if (!isFileTypeAllowed) {
alert("文件类型不支持");
return false;
}
if (this.maxCount === 1) {
return true;
}
if (this.maxCount && this.maxCount > this.uploadedFiles.length) {
return true;
} else {
alert(`最多只能上传${this.maxCount}个文件`);
return false;
}
},
upload(e) {
const formData = new FormData();
const files = Array.from(e.target.files);
if (!files.length) return;
for (let i = 0; i < files.length; i++) {
if (this.beforeUpload(files[i])) {
formData.append("files", files[i]);
}
}
// 文件上传接口
fetch(this.uploadUrl, {
method: "POST",
body: formData,
})
.then(function (response) {
return response.json();
})
.then((data) => {
if (data.success) {
this.$emit("success", data);
} else {
this.$emit("fail", data);
}
this.$refs.fileInput.value = ""; //清空input的value值,避免上传同一个文件的时候无法触发change事件
})
.catch(function (error) {
console.log(error);
});
},
getUploadedFiles: function () {
const files = Array.from(this.$refs.fileInput.files);
const uploadedFiles = [];
for (let i = 0; i < files.length; i++) {
uploadedFiles.push({
name: files[i].name,
url: URL.createObjectURL(files[i]),
});
}
this.uploadedFiles = uploadedFiles;
},
handleRemove(file) {
this.uploadedFiles.splice(this.uploadedFiles.indexOf(file), 1);
},
},
data() {
return {
uploadedFiles: [], //已上传的文件
};
},
mounted() {
if (this.$slots.default) {
this.$slots.default.forEach((vnode) => {
if (vnode.tag) {
vnode.elm.addEventListener("click", () => {
this.$refs.fileInput.click();
});
}
});
}
},
};
</script>
<style>
.hide-input-file {
position: absolute;
visibility: hidden;
width: 0;
height: 0;
}
.uploaded-file {
margin-right: 10px;
display: inline-block;
vertical-align: middle;
position: relative;
cursor: pointer;
}
.uploaded-file .file-name {
font-size: 14px;
max-width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
vertical-align: middle;
margin-left: 5px;
cursor: pointer;
-webkit-touch-callout: none; /* iOS Safari禁止长按链接与图片弹出上下文菜单 */
}
.uploaded-file .close-icon {
display: inline-block;
vertical-align: middle;
position: absolute;
top: 0;
right: -10px;
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
background-color: rgba(0, 0, 0, 0.4);
border-radius: 50%;
color: #fff;
cursor: pointer;
transition: all 0.3s;
user-select: none;
-webkit-touch-callout: none;
}
.uploaded-file .close-icon:hover {
background-color: rgba(0, 0, 0, 0.6);
transform: scale(1.2);
}
</style>
三、使用示例
- 在Vue项目中引入UploadFile.vue 组件
<template>
<div>
<upload-file
:multiple="true"
:uploadUrl="'/file/upload' + '?access_token=' + accessToken"
@success="handleUploadSuccess"
@fail="handleUploadFail"
>
<div class="upload-file-btn">上传文件</div>
</upload-file>
</div>
</template>
<script>
import UploadFile from "@/components/UploadFile.vue";
export default {
name: "FileUploadPage",
components: { UploadFile },
data() {
return {
accessToken: "",
};
},
methods: {
handleUploadSuccess(data) {
console.log("上传成功", data);
},
handleUploadFail(data) {
console.log("上传失败", data);
},
},
mounted() {
this.accessToken = localStorage.getItem("access_token");
},
};
</script>
在以上示例中,我们引入了 UploadFile 组件,并给组件传递多个 props 值,它们分别是:multiple(是否可多选,默认为 false)、uploadUrl(文件上传接口地址)。我们通过添加额外的 slot 到组件中,来定制自己的上传按钮。
- 使用 UploadFile.vue 组件上传文件限制类型和数量
<template>
<div>
<upload-file
:multiple="true"
:uploadUrl="'/file/upload' + '?access_token=' + accessToken"
:max-count="3"
:file-types="['.jpg', '.png']"
@success="handleUploadSuccess"
@fail="handleUploadFail"
>
<div class="upload-file-btn">上传图片(最多三张)</div>
</upload-file>
<div>
<div class="uploaded-file" v-for="file in uploadedFiles" :key="file.name">
<img :src="file.url" alt="上传的图片" width="100" height="100" />
<div class="file-name">{{ file.name }}</div>
<div class="close-icon" @click="handleRemove(file)">X</div>
</div>
</div>
</div>
</template>
<script>
import UploadFile from "@/components/UploadFile.vue";
export default {
name: "FileUploadPage",
components: { UploadFile },
data() {
return {
uploadedFiles: [],
accessToken: "",
};
},
methods: {
handleUploadSuccess(data) {
console.log("上传成功", data);
this.getUploadedFiles();
},
handleUploadFail(data) {
console.log("上传失败", data);
},
getUploadedFiles() {
this.$refs.uploadedFiles = this.$refs.uploadFile.uploadedFiles;
this.uploadedFiles = this.$refs.uploadFile.uploadedFiles;
},
handleRemove(file) {
this.$refs.uploadFile.handleRemove(file);
this.uploadedFiles = this.$refs.uploadFile.uploadedFiles;
},
},
mounted() {
this.accessToken = localStorage.getItem("access_token");
},
};
</script>
在以上示例中,我们除了给 UploadFile 组件传送常规的属性外,额外传递了两个属性:file-types和max-count,它们表示的是文件上传时允许的文件类型和文件数量。在页面中,我们绑定了success和fail事件,可以根据上传结果做出相应的处理。在上传完成之后,我们还会根据上传成功的数据,动态展示出已经上传的文件。
至此,我们就完成了一个通用的上传文件组件,并实现了在Vue项目中使用该组件的示例。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue开发之封装上传文件组件与用法示例 - Python技术站