Vue3版本
<script setup lang="ts">
import { reactive, nextTick } from "vue";
import { useMainStore } from "../../../store";
const store = useMainStore();const props = defineProps<{ accept?: string }>();const emits = defineEmits<{ (e: "fileChange", value: File): void }>();const data = reactive({borderColor: "#000",file: null as File,show: true,
});const handleFile = (file: File) => {console.log(file);data.file = file;emits("fileChange", file);
};const preventDefaultEvent = (e: DragEvent) => {e.preventDefault();data.borderColor = "#000";
};const onDragOver = (e: DragEvent) => {console.log("OVER", store.themeColor);e.preventDefault();data.borderColor = store.themeColor;
};const onDrop = (e: DragEvent) => {data.borderColor = "#000";e.stopPropagation();e.preventDefault();const files = e.dataTransfer.files;const file = files[0];if (!file) {return;}handleFile(file);
};const onFileChange = (e: Event) => {data.show = false;handleFile((e.target as HTMLInputElement).files[0]);nextTick(() => {data.show = true;});
};
</script><template><label for="upload-id"><divclass="upload-container flex":style="{ borderColor: data.borderColor }"@dragleave="preventDefaultEvent"@dragenter="preventDefaultEvent"@dragover="onDragOver"@drop="onDrop"ref="select_frame"><p>{{ data.file?.name }}</p></div><input v-if="data.show" @change="onFileChange" :accept="props.accept" style="display: none" type="file" name="" id="upload-id" /></label>
</template><style scoped lang="less">
@import "../../../assets/style/theme.less";
.upload-container {width: 400px;height: 200px;background-color: #eee;border-radius: 6px;border: 1px dashed;
}
.upload-container:hover {border-color: @primary !important;
}
</style>
React版本
import { Box, SxProps, Theme } from "@mui/material";
import { ChangeEvent, InputHTMLAttributes, PropsWithChildren, useState } from "react";interface DragUploadProps {onFileChange: (files: FileList) => void;sx?: SxProps<Theme>;className?: string;accept?: InputHTMLAttributes<HTMLInputElement>["accept"];
}
export default function DragUpload(props: PropsWithChildren<DragUploadProps>) {const { sx = {}, className, accept } = props;const [show, setShow] = useState(true);const onFileChange = (e: ChangeEvent<HTMLInputElement>) => {const files = e.target.files;handleFile(files);};const preventDefaultEvent = (e: DragEvent) => {e.preventDefault();};const onDragOver = (e: DragEvent) => {console.log("OVER", "store.themeColor");e.preventDefault();};const onDrop = (e: DragEvent) => {e.stopPropagation();e.preventDefault();const files = e.dataTransfer.files;const file = files[0];if (!file) {return;}handleFile(files);};const handleFile = (files: FileList) => {console.log(files);setShow(false);Promise.resolve().then(() => {setShow(true);});props.onFileChange(files);};return (<label htmlFor="upload-id">{}<BoxonDragLeave={preventDefaultEvent}onDragEnter={preventDefaultEvent}onDragOver={onDragOver}onDrop={onDrop}sx={{ borderRadius: 1.5, border: "1px dashed", ...sx }}className={"pointer " + className}>{props.children}{show && <input onChange={onFileChange} accept={accept} style={{ display: "none" }} type="file" name="" id="upload-id" />}</Box></label>);
}