当前位置: 首页 > news >正文

手写拖动上传组件(Vue3/React)

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">
    <div
      class="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"];
}

/**
 * @function React.Component
 * @description 拖动上传文件
 */
export default function DragUpload(props: PropsWithChildren<DragUploadProps>) {
  const { sx = {}, className, accept } = props;
  const [show, setShow] = useState(true);
  //   const [border];

  const onFileChange = (e: ChangeEvent<HTMLInputElement>) => {
    const files = e.target.files;
    handleFile(files);
  };

  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(files);
  };

  const handleFile = (files: FileList) => {
    console.log(files);
    setShow(false);
    Promise.resolve().then(() => {
      setShow(true);
    });
    props.onFileChange(files);
    // setTimeout(() => {
    //   setShow(true);
    // }, 0);
  };

  return (
    <label htmlFor="upload-id">
      {/* @ts-ignore */}
      <Box
        onDragLeave={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>
  );
}

相关文章:

  • 我的网站百度找不到/系统优化方法
  • 广州建网站的网络公司/网络营销就是
  • 论文答辩ppt范例模板/360优化大师旧版
  • 织梦教育网站模板/站长工具是干嘛的
  • 哪个网站可以上传设计的作品/营销型网站建设推荐
  • 网站制作的网站开发/seo快速排名上首页
  • 经济学学习(宏观)
  • Android入门第58天-真机调试
  • 【信管9.1】​项目沟通及过程
  • 《Linux Shell脚本攻略》学习笔记-第十章
  • 工作流代码
  • 使用批处理__更改ip
  • 第一章 TCP/IP 协议
  • 前端面试当中 js原型及原型链常考知识点
  • 【代码随想录】343. 整数拆分
  • 使用nginx搭建HTTP FLV流媒体服务器
  • 11 Java接口(语法、规范、微观宏观接口)
  • 前端学习路线(包括计算机基础,算法,项目开发等学习路径)