基于vue实现的图片上传功能,简单的封装,可以直接根据自己的需求修改
效果图
案例中的小图标引用了阿里云矢量图标库,建议换成自己的
<link rel="stylesheet" href="//at.alicdn.com/t/font_2400323_baxifjc4jkt.css">
html部分
<template> <div class="upload-img"> <ul class="upload-list"> <li v-for="(item,index) in picList" :key="index"> <img :src="item" alt=""> <div class="caozuo"> <i @click="previewImg(item,index)" class="iconfont icon-fangda"></i> <i @click="deleteImg(item,index)" class="iconfont icon-delete"></i> </div> </li> <li class="add-img"> <input @change="fileChange" type="file" > <i v-if="!loading" class="iconfont icon-tianjia"></i> <i v-else class="iconfont loading icon-jiazai"></i> </li> </ul> <div class="preview-box" v-if="ispreview" @click.self="ispreview=false"> <img :src="previewItem" alt=""> </div> </div> </template>
js部分
<script> export default{ data(){ return { picList:['https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3269311786,2664508790&fm=26&gp=0.jpg', 'https://t7.baidu.com/it/u=3358371731,3444613872&fm=193&f=GIF', 'https://t7.baidu.com/it/u=2658433172,2362704784&fm=193&f=GIF'], loading:false, //加载效果 previewItem:'', //用于预览 ispreview:false, //是否打开预览 } }, props:{ num:{ type:Number, default:3 //限制图片的张数 } }, mounted(){ }, methods:{ fileChange(e){ var arr=e.target.files; var picList=this.localPreview(arr) if(this.picList.length==this.num){ alert('最多只能上传'+this.num+'张') return } this.loading=true setTimeout(()=>{ this.picList.push(...picList) this.loading=false },3000) this.$emit('changepic',this.picList) //下面是调用接口时候用的 // var formData = new FormData() // arr.forEach(item=>{ // formData.append('file',item) // }) /**发起请求自己根据自己的需求写**/ // }, //删除图片 deleteImg(item,index){ this.picList.splice(index,1) this.$emit('changepic',this.picList) }, //预览图片 previewImg(item,index){ this.ispreview=true this.previewItem=item this.$emit('preview',item) }, /***获取图片上传的本地路径****/ localPreview(list){ //这里是利用文件读取对象读取图片 // var reader = new FileReader(); // reader.readAsDataURL(file); // var url=null; // reader.onload=function(){ // url=reader.result; // } var url=null; var arr=[] list.forEach(item=>{ arr.push(window.URL.createObjectURL(item)) //利用window.URL.createObjectURL转换 }) return arr } }, } </script>
css部分
ul,li{ padding:0px; margin:0px; list-style: none; } p{ padding:0px; margin:0px; } .upload-list{ width:100%; display:flex; flex-wrap: wrap; } .upload-list li{ width:100px; position:relative; margin:5px; height:100px; border:1px solid black; overflow:hidden; box-sizing: border-box; } .upload-list li:hover .caozuo{ display:flex; } .caozuo{ display:none; background:rgba(0,0,0,0.5); position:absolute; left:0px; top:0px; width:100%; height:100%; justify-content: center; align-items: center; color:white; letter-spacing: 5px; } .caozuo .iconfont{ font-size:25px; } .upload-list li img{ width:100%; position:absolute; left:0px; top:50%; transform: translateY(-50%); } .upload-img{ width:100%; } .add-img{ width:32%; display:flex; justify-content: center; align-items: center; } .add-img .iconfont{ font-size:40px; } .add-img input{ position:absolute; left:0px; bottom:0px; width:100%; height:100%; opacity: 0; z-index:1; } .loading{ animation:carton 5s infinite; } .preview-box{ display:flex; justify-content: center; align-items: center; position:fixed; top:0px; left:0px; right:0px; bottom:0px; background:rgba(0,0,0,0.5) } .preview-box img{ max-width:100%; max-height:100%; } @keyframes carton { from {transform:rotate(0deg);} to {transform:rotate(360deg);} }