{ "slug": "dragupload", "end": "vue3", "curated": true, "summary": "Vue 3 拖拽上传:拖入或点击选择文件,内部模拟上传进度并生成图片缩略图。", "usage": [ "本端没有任何 props、emit 与插槽, 挂上即用,文件列表由内部 files ref 维护(DragUpload.vue3.vue:25)。", "拖拽事件用 @dragover.prevent / @drop.prevent 组合,避免浏览器直接打开被拖入的文件(DragUpload.vue3.vue:3)。", "点击区域通过 file.click() 转发到隐藏的 input[type=file],选完即把 e.target.value 清空,便于重复选同一个文件(DragUpload.vue3.vue:42)。", "图片且小于 2MB 时用 FileReader.readAsDataURL 生成缩略图,其它类型统一显示「文件」文字(DragUpload.vue3.vue:33)。", "进度是 setInterval 每 220ms 随机递增的演示数据,到 100 即标记 done 并清除定时器(DragUpload.vue3.vue:44)。" ], "bestPractices": [ "进度与完成态都是本地模拟,没有真实上传通道,接入后端时需要自行替换 simulate 并接管 files 结构(DragUpload.vue3.vue:44)。", "删除是按下标 id 过滤数组,id 由时间戳加随机串生成;同批次内不会重复,但长时间挂载后 id 会越来越长(DragUpload.vue3.vue:31)。", "thumb 只在图片且小于 2MB 时生成,其余类型 key 仍存在但为空串,模板用 v-if 分支渲染占位文字(DragUpload.vue3.vue:10)。" ], "apiCarrier": { "kind": "props", "note": "本端无 defineProps / defineEmits / defineExpose,唯一可用的定制面是模板类名与 is-over 状态类,因此表中列出的是样式钩子而非 prop。", "table": [ { "name": "kole-upload-drop", "type": "class", "desc": "拖拽投放区容器类名;拖拽经过时附加 is-over 状态类" }, { "name": "kole-upload-item", "type": "class", "desc": "单个文件行容器,进度条与状态文字均在此基础上挂子类" }, { "name": "kole-upload-del", "type": "class", "desc": "删除按钮类名,点击后从 files 中移除该行" }, { "name": "is-over", "type": "state class", "desc": "拖拽悬停态::class=\"{ 'is-over': over }\",可用于高亮投放区" } ] }, "a11y": [ "拖拽区是 div + @click,没有 role、tabindex 与键盘处理,纯键盘用户完全无法选择文件;建议由业务在其上叠加真实 button(DragUpload.vue3.vue:3)。", "隐藏的 file input 用 style=\"display:none\" 且无 label,读屏与键盘都访问不到;进度条只有数字百分比,没有 role=\"progressbar\"(DragUpload.vue3.vue:7)。" ], "resources": [ { "file": "frameworks/DragUpload.vue3.vue", "kind": "Vue 3 组件", "desc": "dragupload 的 Vue 3(