前几天公司做一个临时招聘页,为了方便直接使用了Vue CDN 链接,组件也直接写进了 JS 文件,也没有做模块化分割。不过页面需要上传个人简历照片等信息,于是便手写了一个多文件上传组件,下面附上源码和一些注释
主要功能
- 支持拖拽上传
- 支持多文件选择
- 支持复制粘贴上传(由于浏览器限制,粘贴功能的有使用范围,可以用其他软件截图,比如QQ,然后在上传域粘贴即可)
- 支持上传预览
- 页面效果图:
- mutipleUpload.vue
复制代码点击 “+” 号或拖拽文件到此处{ {subtitle}}×已选择 { {images.length}} 张图片,共 { {getSize}}
下面是样式
/* 容器 */ .im-upload-container { border: 1px solid #d2d2d2; border-radius: 0.3em; } .im-upload-container .im-upload-foot { display: block; height: 46px; line-height: 46px; padding: 0 15px; border-top: 1px solid #d2d2d2; } /* 中间的提示 */ .im-upload-tips { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); user-select: none; } .im-upload-area { position: relative; display: block; padding: 15px 0 0 15px; } .im-upload-area:hover { box-shadow: 0 0 0 1px #d2d2d2 inset; } .im-upload-area > .im-upload-tips { color: #ddd; font-size: 22px; cursor: default; text-align: center; } .im-upload-area > .im-upload-tips > .im-upload-subtitle { font-size: 18px; } .im-upload-area > .im-upload-item { position: relative; display: inline-block; width: 100px; height: 100px; margin-bottom: 15px; margin-right: 15px; overflow: hidden; box-shadow: 0 0 0 0 #d2d2d2; transition-duration: 0.2s; border-radius: 0.3em; } .im-upload-area > .im-upload-item.im-uploaded { box-shadow: 0 0 0 3px #008B45; } .im-upload-area > .im-upload-item.im-uploaded:hover { box-shadow: 0 0 5px 5px #006231; } .im-upload-area > .im-upload-item::before { content: attr(data-title); display: block; width: 100%; height: 0; position: absolute; background: rgba(35, 35, 35, 0.6); line-height: 25px; text-align: center; color: #fefefe; overflow: hidden; transition-duration: 0.2s; } .im-upload-area > .im-upload-item:hover { box-shadow: 0 0 5px 5px #bebebe; } .im-upload-area > .im-upload-item:hover::before { height: 25px; } .im-upload-area > .im-upload-item > .im-upload-close { position: absolute; display: block; top: 3px; right: 3px; z-index: 1; background: #000; color: #ffffff; width: 18px; height: 18px; text-align: center; border-radius: 50%; } .im-upload-area > .im-upload-item > img { vertical-align: middle; height: 100%; } .im-upload-add { margin-bottom: 15px; position: relative; display: inline-block; width: 100px; height: 100px; border: 3px dashed #d2d2d2; transition-duration: 0.2s; vertical-align: top; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; border-radius: 0.3em; cursor: pointer; } .im-upload-add > .im-upload-sign { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); font-size: 140px; color: #d2d2d2; transition-duration: 0.2s; } .im-upload-add > .im-upload-sign:hover { color: #bebebe; } .im-upload-add:hover { border-color: #bebebe; } .float-right { float: right; }复制代码
看了很多上传组件,包括一些组件库,实现都很完善,也很强大,这儿主要介绍一下这个组件的一些关键点:
- 粘贴上传:暂时没发现哪些组件实现的这个功能,实现方式主要是对整个上传域监听一个 paste 事件,其实这个事件还可以做更多事,不过这需要结合一定的场景,可以天马行空发挥一下想象力;
- 拖拽上传:和 mousedown、mousemove、mouseup 写拖拽控件相似,注意一下频繁触发事件即可,这儿用了一个变量 dragOver 来屏蔽多余的触发;
- 选择文件按钮:控件在列表末尾放了一个大大的“+”号,这也是很多地方比较通用的方式,这个“+”号实际是一个 label 标签,利用的 label 和 input 标签的传递特性(通过 input 的 id 绑定,这也是为什么每个组件都有自己的唯一 id 的原因),此时就可以完全隐藏 input 标签,然后对 label 标签任意发挥样式的书写。
- 其他:图片预览用到了 FileReader ,这是 h5 的特性,它的 readAsDataURL 方法可以直接读取图片文件为一个 base64 编码的 url,可以直接用 img 标签显示。
也可以放进 background 里面,但是用背景渲染出来的样式很卡,也做不了更多事,不建议这么用。
- 如果出现“+”号位置对不齐的情况加上(是因为字体的原因):
html { font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei","微软雅黑", Arial, sans-serif;}复制代码
- 注意:没有针对不同文件类型的处理