html实现拖拽上传
最近公司需要有一个拖拽上传的功能,但是由于在开发前,某某人规定了只能使用某个组件库😅,而组件库内没有拖拽上传的例子,所以我在这里写一个拖拽上传的功能😁.3. 这里有用到Bootstrap5的class,所以html部分的样式需要自己更改。1. 这里上传成功后的提示用的是primevue组件库,可以不用管。2. 目前这里只是单文件上传,如果有需求可以自行更改。4. 目前这边就是按钮上传以及拖拽上
·
最近公司需要有一个拖拽上传的功能,但是由于在开发前,使用的组件库内没有拖拽上传的例子,所以我在这里写一个拖拽上传的功能😁.
首先写一个组件(拖拽上传的组件)
1. 这里上传成功后的提示用的是primevue组件库,可以不用管
2. 目前这里只是单文件上传,如果有需求可以自行更改
3. 这里有用到Bootstrap5的class,所以html部分的样式需要自己更改
4. 目前这边就是按钮上传以及拖拽上传
<template>
<div v-if="type === 0">
<a @click="handleClickUpload" class="btn btn-primary">{{buttonText}}</a>
<input @change="handleUpload" :multiple="isMultiple" ref="uploadRef" type="file" class="d-none" />
</div>
<div v-else-if="type === 1" :style="{'width': width, 'height': height}" class="upload-component position-relative">
<div class="h-100 w-100 position-absolute z-index-1">
<input @change="handleUpload" :multiple="isMultiple" type="file" />
</div>
<img v-if="uploadImageUrl" :src="uploadImageUrl" alt="..." class="w-100 h-100 position-absolute top-0" style="object-fit: cover;" />
<div v-else class="upload-tips">{{uploadTips}}</div>
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, toRefs, watchEffect, ref } from 'vue';
import { useToast } from "primevue/usetoast";
export default defineComponent({
name: "upload-component",
props: {
// 组件的类型 - 0: 按钮 1: 拖拽
type: {
type: Number,
default: 0,
},
// 上传类型 - 0: 图片 补充...
uploadType: {
type: Number,
default: 0,
},
// 是否支持上传多个
isMultiple: {
type: Boolean,
default: false,
},
// 图片路径(上传成功后回显 - 仅单张图片) - 拖拽类型生效
uploadImageUrl: {
type: String,
default: "",
},
// 宽度 - 拖拽类型生效
width: {
type: String,
default: "200px",
},
// 高度 - 拖拽类型生效
height: {
type: String,
default: "200px",
},
// 上传的文字提示
uploadTips: {
type: String,
default: "将图片拖放到此处或点击上传",
},
// 上传按钮的文字
buttonText: {
type: String,
default: "点击上传",
},
},
setup(props, { emit }) {
const toast = useToast();
const uploadRef = ref();
const state = reactive({
// 组件的类型
type: props.type,
// 允许上传的类型
uploadType: props.uploadType,
// 是否支持上传多个
isMultiple: props.isMultiple,
// 图片路径(上传成功后回显 - 仅单张图片)
uploadImageUrl: props.uploadImageUrl,
// 上传的文字提示
uploadTips: props.uploadTips,
// 宽度
width: props.width,
// 高度
height: props.height,
// 上传的地址
uploadFileUrl: "这边是上传的路径地址",
});
/** 监听... */
watchEffect(() => {
state.type = props.type;
state.uploadType = props.uploadType;
state.uploadImageUrl = props.uploadImageUrl;
state.isMultiple = props.isMultiple;
});
/** 处理点击上传 */
const handleClickUpload = () => {
uploadRef.value.click();
}
/** 处理上传之前的钩子 */
const handleBeforeUpload = (files: any) => {
let result = true;
// 判断上传类型
for(const item of files) {
if(state.uploadType === 0 && !item.type.includes("image")) {
result = false;
break;
}
}
if(!result) {
toast.add({severity: 'warn', summary: '提示', detail: '当前上传的文件类型不支持', life: 1500});
return result;
}
return result;
}
/** 处理上传成功后 */
const handleAfterUpload = (files: any) => {
// 目前只是单个上传 - 多个上传以后需求用到再改
let file = null as any;
if(!state.isMultiple) {
file = files[0];
}
else {
file = files[0];
}
// 将file文件设置成form数据
const fileForm = new FormData();
fileForm.append("file", file);
// 创建XMLHttpRequest对象
const xhr = new XMLHttpRequest();
// 设置请求方式以及路径
xhr.open("POST", state.uploadFileUrl);
// 发送请求
xhr.send(fileForm);
// 监听请求的结果
xhr.addEventListener("load", () => {
const response = JSON.parse(xhr.response);
toast.add({severity: 'success', summary: '提示', detail: '上传成功', life: 1500});
emit("handleUploadSuccess", response);
});
}
/** 处理上传操作 */
const handleUpload = (event: any) => {
// 上传之前
if(!handleBeforeUpload(event.target.files)) {
return;
}
// 上传后
handleAfterUpload(event.target.files);
}
return {
...toRefs(state),
uploadRef,
handleUpload,
handleBeforeUpload,
handleClickUpload,
}
}
});
</script>
<style scoped lang="scss">
.upload-component {
width: 400px;
height: 400px;
border-radius: 4px;
border: 1px dashed #d9d9d9;
background: #f5f5f5;
cursor: pointer;
position: relative;
overflow: hidden;
&:hover {
transition: .2s;
border-color: #409eff;
}
.upload-tips {
font-size: 12px;
color: #999;
line-height: 20px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
width: 70%;
}
input {
cursor: pointer;
width: 100%;
height: 100%;
position: absolute;
left: 0;
padding-bottom: 30px;
transform: translateY(-30px);
box-sizing: content-box;
}
}
</style>
最后就是引入组件使用就好,组件引入很简单这里就不展示代码,效果图是:
更多推荐
已为社区贡献3条内容
所有评论(0)