news 2026/3/11 13:00:21

vue3拖拽+粘贴的综合上传器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
vue3拖拽+粘贴的综合上传器

效果

组件

<template><divclass="upload-wrapper"><divref="dropZoneRef"class="upload-area"tabindex="0":class="{'drag-over': isDragOver,'is-limit': isLimitReached }"@dragenter.prevent="isDragOver = true"@dragover.prevent="isDragOver = true"@dragleave.prevent="isDragOver = false"@drop.prevent="onDrop"@paste.stop.prevent="onPaste"><divclass="inner-content"><templatev-if="!isLimitReached"><pv-if="!isFocused"class="main-hint">{{ placeholder }}</p><pv-elseclass="active-hint">✅ 已激活:现在可以按 Ctrl + V 粘贴了</p></template><templatev-else><pclass="limit-hint">已达到上传数量上限 ({{ limit }}个)</p></template><pclass="sub-hint">支持 {{ acceptLabel }} (单文件最大 {{ maxSize }}MB)</p><buttonclass="btn-select":disabled="isLimitReached"@click.stop="triggerFileInput">选择文件</button></div><inputtype="file"ref="fileInputRef":multiple="multiple":accept="accept"hidden@change="onFileChange"></div><divclass="preview-grid"v-if="fileList.length > 0"><divv-for="(file, index) in fileList":key="file.id"class="preview-item"><imgv-if="file.type ==='image'":src="file.url"/><videov-else:src="file.url"muted@loadedmetadata="e => e.target.currentTime = 0.1"></video><divclass="file-meta">{{ (file.raw.size / 1024).toFixed(0) }}kb</div><buttonclass="delete-btn"@click="removeFile(index)">&times;</button></div></div></div></template><scriptsetup>import{ref,computed,onMounted,onUnmounted,watch}from'vue';// --- 定义 Model (替代 modelValue prop 和 update:modelValue emit) ---constmodel=defineModel({type:Array,default:()=>[]});// --- 其他 Props ---constprops=defineProps({accept:{type:String,default:'image/*,video/*'},maxSize:{type:Number,default:10},limit:{type:Number,default:9},multiple:{type:Boolean,default:true},placeholder:{type:String,default:'点击此处激活粘贴功能'}});// --- 其他 Emits ---constemit=defineEmits(['error','remove']);// --- 状态管理 ---constfileList=ref([]);// 内部维护包含预览URL的对象数组constisDragOver=ref(false);constisFocused=ref(false);constdropZoneRef=ref(null);constfileInputRef=ref(null);constisLimitReached=computed(()=>fileList.value.length>=props.limit);constacceptLabel=computed(()=>props.accept.replace(/\/\*/g,''));// --- 核心逻辑 ---// 处理粘贴constonPaste=(e)=>{if(document.activeElement!==dropZoneRef.value||isLimitReached.value)return;constitems=e.clipboardData?.items;if(!items)return;constfiles=[];for(constitemofitems){if(item.kind==='file')files.push(item.getAsFile());}handleFiles(files);};// 核心文件校验与处理consthandleFiles=(incomingFiles)=>{constfilesArray=Array.from(incomingFiles);constnewPreviews=[];for(constfileoffilesArray){if(fileList.value.length+newPreviews.length>=props.limit){emit('error','超过最大上传数量限制');break;}constisImage=file.type.startsWith('image/');constisVideo=file.type.startsWith('video/');if(!isImage&&!isVideo){emit('error',`不支持的文件类型:${file.name}`);continue;}if(file.size>props.maxSize*1024*1024){emit('error',`文件超过${props.maxSize}MB:${file.name}`);continue;}newPreviews.push({id:crypto.randomUUID(),type:isImage?'image':'video',url:URL.createObjectURL(file),raw:file});}if(newPreviews.length>0){fileList.value.push(...newPreviews);// 直接更新 model 值model.value=fileList.value.map(f=>f.raw);}};consttriggerFileInput=()=>{if(!isLimitReached.value)fileInputRef.value?.click();};constonFileChange=(e)=>{handleFiles(e.target.files);e.target.value='';};constonDrop=(e)=>{isDragOver.value=false;if(!isLimitReached.value)handleFiles(e.dataTransfer.files);};constremoveFile=(idx)=>{constremoved=fileList.value[idx];URL.revokeObjectURL(removed.url);fileList.value.splice(idx,1);// 更新模型model.value=fileList.value.map(f=>f.raw);emit('remove',removed.raw);};// 监听焦点onMounted(()=>{dropZoneRef.value?.addEventListener('focus',()=>isFocused.value=true);dropZoneRef.value?.addEventListener('blur',()=>isFocused.value=false);});// 内存清理onUnmounted(()=>{fileList.value.forEach(f=>URL.revokeObjectURL(f.url));});</script><stylescoped>/* 样式部分保持一致 */.upload-area{border:2px dashed #ccd0d5;border-radius:12px;padding:40px 20px;text-align:center;background:#fafafa;transition:all 0.3s ease;cursor:pointer;outline:none;}.upload-area:focus{border:2px solid #4a90e2;background:#f0f7ff;box-shadow:0 0 15pxrgba(74,144,226,0.2);}.upload-area.drag-over{border-color:#2ecc71;background:#e8f5e9;}.upload-area.is-limit{cursor:not-allowed;background:#f5f5f5;}.main-hint{font-size:1.1rem;color:#666;}.active-hint{font-size:1.1rem;color:#4a90e2;font-weight:bold;}.limit-hint{font-size:1.1rem;color:#e74c3c;font-weight:bold;}.sub-hint{font-size:0.85rem;color:#999;margin:10px 0;}.btn-select{padding:8px 24px;background:white;border:1px solid #ddd;border-radius:6px;cursor:pointer;margin-top:10px;}.preview-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:15px;margin-top:25px;}.preview-item{position:relative;aspect-ratio:1;border-radius:8px;overflow:hidden;background:#000;}.preview-item img, .preview-item video{width:100%;height:100%;object-fit:cover;}.file-meta{position:absolute;bottom:0;left:0;right:0;background:rgba(0,0,0,0.5);color:#fff;font-size:10px;padding:2px 5px;}.delete-btn{position:absolute;top:5px;right:5px;background:rgba(0,0,0,0.5);color:white;border:none;border-radius:50%;width:20px;height:20px;cursor:pointer;}</style>

使用

<template><divclass="form-item"><label>上传素材 (最多3个):</label><MediaUploaderv-model="postFiles":limit="3":maxSize="50"@error="handleUploadError"/></div></template><scriptsetup>import{ref}from'vue';importMediaUploaderfrom'./components/MediaUploader.vue';// 存储原始 File 对象constpostFiles=ref([]);// 错误处理回调consthandleUploadError=(msg)=>{// 此处建议对接项目内的消息提示组件,如 ElMessage 或 message.errorconsole.error('上传校验失败:',msg);};</script>

说明

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/11 11:46:41

基于机器学习的就业岗位推荐系统设计与实现

第一章 系统开发背景与意义 当前就业市场面临“求职难匹配效率低”的双重困境&#xff1a;求职者淹没在海量岗位信息中&#xff0c;难以快速定位适配机会&#xff1b;企业招聘成本持续攀升&#xff0c;优质简历筛选耗时且准确率不足。传统推荐依赖关键词匹配&#xff0c;存在“…

作者头像 李华
网站建设 2026/3/9 3:29:12

AI大模型工程架构全解析:从零基础入门到实战精通,一篇就够了!

文章揭示了AI智能体落地的真相&#xff1a;90%工作是工程架构设计&#xff0c;仅10%涉及大模型本身。详细拆解了智能体落地的14个层次&#xff0c;包括算力、基础设施、数据库、ETL、基础模型等&#xff0c;强调企业需全链路打磨而非单点突破。大模型虽是点睛之笔&#xff0c;但…

作者头像 李华
网站建设 2026/3/11 1:36:31

Minimax大模型算法岗面试全攻略:从基础到进阶,收藏这份超详细面经

本文分享了minimax大模型算法岗面试的详细经历&#xff0c;涵盖一面和二面的各类问题&#xff0c;包括大模型基础知识、项目经验、算法实现等。面试涉及位置编码、预训练推理、超长上下文处理、PPO与DPO算法对比等内容&#xff0c;还包含编程题。一面 自我介绍和项目介绍介绍一…

作者头像 李华
网站建设 2026/2/26 9:46:42

采购系统值不值得上?先看它能不能接住这几件日常工作

干采购的兄弟们&#xff0c;是不是经常被供应商催单到怀疑人生&#xff1f;合同漏签了&#xff0c;客户投诉上门库存对不上&#xff0c;月底盘点直接手忙脚乱审批流程卡在领导手机上&#xff0c;等得花儿都谢了我见过太多采购同事&#xff0c;半夜还在群里问谁有空批个单子&…

作者头像 李华
网站建设 2026/3/10 23:30:41

一文读懂计算机网络安全:核心要义、防护体系与实战资源清单

一、网络安全原理 网络安全包含两大部分内容&#xff1a;一是网络系统安全&#xff0c;二是网络上的信息安全。它涉及网络系统的可靠性、稳定性&#xff0c;以及网络上信息的保密性、完整性、可用性、真实性和可控性等。 网络系统安全&#xff1a;指保证信息处理和传输系统的…

作者头像 李华
网站建设 2026/3/4 4:26:32

学网络安全,一张清单就够了!五大核心技术通俗解析与快速入门指南

网络安全技术是保护网络不受未经授权访问、破坏或盗取信息的重要手段。以下是五种零基础也能看懂的网络安全技术&#xff1a; 1.防火墙技术&#xff1a;防火墙是一种网络安全设备&#xff0c;用于监控和控制进入或离开网络的流量。它可以识别不安全的数据包&#xff0c;并阻止…

作者头像 李华