开发预览 更新于 2026-05-10

Dropzone 文件拖拽上传

拖拽 + 点击双触发的文件选择器,内置文件列表、进度条与 reject 回调。

基础用法

v-model 绑定一个 File[]。把文件拖进虚线框,或点击区域弹出文件对话框;选完会出现一个紧凑的文件列表,每行带尺寸和移除按钮。

点击或拖拽文件到此区域上传
支持拖入或点击选择,多文件均可
<script setup lang="ts">
import { ref } from 'vue';
import { CfDropzone } from '@chufix-design/vue';

const files = ref<File[]>([]);
</script>

<template>
<CfDropzone v-model="files" hint="支持拖入或点击选择,多文件均可" />
</template>
import { useState } from 'react';
import { CfDropzone } from '@chufix-design/react';

export default function Demo() {
const [files, setFiles] = useState<File[]>([]);
return (
  <CfDropzone
    value={files}
    hint="支持拖入或点击选择,多文件均可"
    onChange={setFiles}
  />
);
}

约束 + 拒绝回调

accept / maxSize / maxFiles 控制接受范围;任何被拒绝的文件都会通过 reject(Vue)/ onReject(React)回调出来,附带具体原因('too-large' | 'too-many' | 'wrong-type' | 'duplicate')。

点击或拖拽文件到此区域上传
只接受图片,单文件最大 1 MB,最多 3 个
<script setup lang="ts">
import { ref } from 'vue';
import { CfDropzone, type DropzoneRejection } from '@chufix-design/vue';

const files = ref<File[]>([]);

function onReject(items: DropzoneRejection[]) {
// 自行处理,例如触发 Toast
}
</script>

<template>
<CfDropzone
  v-model="files"
  accept="image/*"
  :max-size="1024 * 1024"
  :max-files="3"
  hint="只接受图片,单文件最大 1 MB,最多 3 个"
  @reject="onReject"
/>
</template>
import { useState } from 'react';
import { CfDropzone, type DropzoneRejection } from '@chufix-design/react';

export default function Demo() {
const [files, setFiles] = useState<File[]>([]);
return (
  <CfDropzone
    value={files}
    accept="image/*"
    maxSize={1024 * 1024}
    maxFiles={3}
    hint="只接受图片,单文件最大 1 MB,最多 3 个"
    onChange={setFiles}
    onReject={(items: DropzoneRejection[]) => console.warn(items)}
  />
);
}

上传进度

把外部上传状态用 statuses(Vue / React)传进来,长度需与 modelValue / value 一致。status 取值 'pending' | 'uploading' | 'success' | 'error'progress 0 ~ 100;error 仅在 status === 'error' 时显示。

下面这个 demo 用 setTimeout 假装上传,实际项目里把 statuses 接到 fetch / XHR 的 progress 事件即可。

点击或拖拽文件到此区域上传
选择文件后会模拟上传进度
<script setup lang="ts">
import { ref, watch } from 'vue';
import { CfDropzone, type DropzoneFileStatus } from '@chufix-design/vue';

const files = ref<File[]>([]);
const statuses = ref<DropzoneFileStatus[]>([]);

watch(files, (next) => {
statuses.value = next.map((_, i) =>
  statuses.value[i] ?? { progress: 0, status: 'pending' }
);
});
</script>

<template>
<CfDropzone v-model="files" :statuses="statuses" />
</template>
import { useState, useEffect } from 'react';
import { CfDropzone, type DropzoneFileStatus } from '@chufix-design/react';

export default function Demo() {
const [files, setFiles] = useState<File[]>([]);
const [statuses, setStatuses] = useState<DropzoneFileStatus[]>([]);
useEffect(() => {
  setStatuses((prev) =>
    files.map((_, i) => prev[i] ?? { progress: 0, status: 'pending' })
  );
}, [files]);
return <CfDropzone value={files} statuses={statuses} onChange={setFiles} />;
}

API

属性类型默认值说明
modelValue (Vue) / value (React)File[][]当前文件数组
acceptstring<input>accept,逗号分隔;支持 image/*.ext 形式
multiplebooleantrue单选 / 多选;false 时新选会替换旧值
maxSizenumber单文件最大字节数
maxFilesnumber总数量上限
disabledbooleanfalse禁用
size'sm' | 'md' | 'lg''md'尺寸
hintstring副标题文字
statusesDropzoneFileStatus[]与文件平行的状态数组:{ progress, status, error }
hideListbooleanfalse不渲染内置文件列表,由你自定义

事件:update:modelValue / change / reject / remove(React 端:onChange / onReject / onRemove)。

插槽:默认 slot 替换标题区域;#icon 替换默认上传插图(默认来自 CfStatusIllustration variant="upload")。

反馈与讨论

Dropzone 文件拖拽上传 的讨论

0
0 / 600
一键发送
正在加载评论...