前言:
通过vue的element框架的上传功能来封装一个上传图片的插件,支持点击和拖拽。
实现效果1:通过 showFileList 来控制,false是第一种效果,true是第二种,需要使用v-view这个图片查看插件
实现效果2:
实现步骤:
一、先引入相关文件一共两个,一个是uploadImg.vue ,一个是imgView.vue
1、uploadImg.vue
<template><div class="uploadImgBody" v-if="Refresh"><!--展示已上传图片部分--><imgView v-if="!showFileList" class="imgViewDiv" :imageList="fileList" @deleteImg="deleteImg"></imgView><!--上传图片部分--><el-uploadv-if="isEdit"class="upload-image"ref="upload":action="action":headers="headers":multiple="multiple":data="data":name="name":with-credentials="cookieOK":show-file-list="showFileList":drag="drag":accept="accept":list-type="listType":auto-upload="autoUpload":file-list="fileList":disabled="is_disabled":on-preview="handlePreview":on-remove="handleRemove":on-success="handleSuccess":on-error="handleError":on-progress="handleProgress":on-exceed="handleExceed":on-change="onChange":before-upload="beforeUpload":before-remove="beforeRemove":http-request="httpRequest"><div slot="default" class="uploadImgDiv"><i class="el-icon-plus"></i><!--提示信息--><div slot="tip" class="el-upload__tip" v-if="tip_text!=''">{{tip_text}}</div></div><!--弹框展示上传以后的图片--><div slot="file" slot-scope="{file}"><imgclass="el-upload-list__item-thumbnail":src="file.url" alt=""><span class="el-upload-list__item-actions"><spanclass="el-upload-list__item-preview"@click="handlePictureCardPreview(file)"><i class="el-icon-zoom-in"></i></span><spanv-if="!disabled"class="el-upload-list__item-delete"@click="handleRemove(file)"><i class="el-icon-delete"></i></span></span></div></el-upload><el-dialog :visible.sync="dialogVisible"><img width="100%" :src="dialogImageUrl" alt=""></el-dialog></div></template><script>import imgView from './imgView'//element的上传文件组件export default {props:{/*** 自动上传参数* */autoUpload:{ // 是否需要选取完自动上传功能type: Boolean,default: false},action:{//上传的地址type: String,default: ''},headers: {//设置上传的请求头部type:Object,default: () => {return {}}},data: {//上传时额外带的参数type:Object,default: () => {return {}}},name:{//上传的文件字段名type: String,default: 'file'},cookieOK:{//支持发送 cookie 凭证信息type: Boolean,default: true},/*** 公共参数* */showFileList:{//是否显示已上传文件列表type: Boolean,default: false},drag:{//是否启用拖拽上传type: Boolean,default: true},accept:{//接受文件类型-图片上传类型-不同的格式之间以逗号隔开type: String,// default:'.doc,.docx,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document'default: '.jpg,.jpeg,.png'},listType:{ // 文件列表的类型 - text/picture/picture-cardtype: String,default: 'picture-card'},fileList:{//已上传的文件列表,type:Array,default: () => {// { 默认格式// name: 'food.jpeg',// url: '/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'// }return [{name: 'food.jpeg',url: '/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]}},is_disabled:{//是否禁止,true是禁止,false不禁止type: Boolean,default: false},multiple:{//是否可以多选type: Boolean,default: true},limit:{//最大允许上传个数type: Number,default: 30},tip_text:{//提示信息type: String,default: ''},/*** 手动上传参数* */needFromUpload:{ // form表单,将上传的file文件通过 formUpload 方法发送出去type: Boolean,default: false},isEdit:{ //是否可编辑type: Boolean,default: true},},watch: {},data() {return {Refresh:true,//强制刷新dialogImageUrl: '',dialogVisible: false,disabled: false,}},created() {},mounted() {},methods: {/*** 上传-默认事件* *///文件列表移除文件时的钩子handleRemove(file, fileList) {console.log('当前移除的是:');console.log(file);},//点击文件列表中已上传的文件时的钩子handlePreview(file) {console.log('当前点击的是'+file);},//文件上传成功时的钩子handleSuccess(response, file, fileList) {console.log('文件上传成功');},//文件上传失败时的钩子handleError(err, file, fileList) {console.log('文件上传失败');},//文件上传时的钩子handleProgress(event, file, fileList) {console.log(file);},//文件超出个数限制时的钩子handleExceed(files, fileList) {console.log('文件超出个数限制');},//覆盖默认的上传行为,可以自定义上传的实现httpRequest(){},//删除文件之前的钩子,参数为上传的文件和文件列表,若返回 false 或者返回 Promise 且被 reject,则停止删除。beforeRemove(file, fileList) {console.log('当前删除的文件'+file);this.fileList.forEach((item,index)=>{if(item == file){this.fileList.splice(index,1)}})},/*** 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用*/onChange(file, fileList) {this.fileList = fileList;console.log('当前的选中文件:');console.log(fileList);},/*** 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。*/beforeUpload(file) {console.log(file);},/*** 上传-自定义事件* */submitUpload() {this.$refs.upload.submit();},//清空已上传的文件列表(该方法不支持在 before-upload 中调用)clearFiles(){this.$refs.upload.clearFiles();this.fileList = [];},//取消上传某个文件abortFiles(file){this.$refs.upload.abort(file);},/*** 手动上传点击确认* */submitUploadSD(){let arr = this.fileList;let str = {fileList:arr}this.$emit('uploadFile',str);},/*** 手动刷新上传组件* */RefreshUpload(){let arr = this.fileList;this.Refresh = false;this.$nextTick(()=>{this.Refresh = true;})},/*** 打开查看图片的弹框* */handlePictureCardPreview(file) {this.dialogImageUrl = file.url;this.dialogVisible = true;},//删除当前图片deleteImg(item){let uid = item.other.uid;this.fileList.forEach((item,index)=>{if(item.uid == uid){this.fileList.splice(index,1)}})}},components: {imgView},beforeDestroy() {}}</script><style lang='scss' scoped>.uploadImgBody{.imgViewDiv{display: inline-block;vertical-align: top;}.upload-image{display: inline-block;}}.upload-image{div{width:100%;height: 100%;}}</style>
2、imgView.vue,这个插件主要是基于v-viewer的封装,如果npm 下载的有问题,无法使用,请点我
<template><viewer :images="images"><div class="imgDiv" v-for="(item,index) in images" :key="'img'+index" @mouseover="mouseOver(index)" @mouseleave="mouseLeave(index)"><img :src="item.src" :key="item.index" width="148" height="148" style="margin-right:10px;"><p class="iconStyle" v-if="item.show" @click="deleteImg(item)"><i class="el-icon-close"></i></p></div></viewer></template><script>import Vue from 'vue';import Viewer from 'v-viewer'import 'viewerjs/dist/viewer.css'Vue.use(Viewer);Viewer.setDefaults({'inline':false,//启用 inline 模式'button':true, //右上角按钮"navbar": true, //底部缩略图"title": true, //当前图片标题"toolbar": true, //底部工具栏"tooltip": true, //显示缩放百分比"movable": true, //是否可以移动"zoomable": true, //是否可以缩放"rotatable": true, //是否可旋转"scalable": true, //是否可翻转"transition": true, //使用 CSS3 过度"fullscreen": true, //播放时是否全屏"keyboard": true, //是否支持键盘"url": "data-source",ready: function (e) {console.log(e.type,'组件以初始化');},show: function (e) {console.log(e.type,'图片显示开始');},shown: function (e) {console.log(e.type,'图片显示结束');},hide: function (e) {console.log(e.type,'图片隐藏完成');},hidden: function (e) {console.log(e.type,'图片隐藏结束');},view: function (e) {console.log(e.type,'视图开始');},viewed: function (e) {console.log(e.type,'视图结束');},zoom: function (e) {console.log(e.type,'图片缩放开始');},zoomed: function (e) {console.log(e.type,'图片缩放结束');}});export default {props: {imageList:Array | Object,//预览传进来的图片地址,这里因为项目中已经定型了,所以传一个string进来,然后手动转 array},watch: {//传来的图片地址imageList(val){let type = Array.isArray(val);if(!type){this.changeArr(val.url);}else{this.changeArrT(val);}},},data () {return {isShow:false,//是否展示预览弹框images:[// {src:'/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3272199364,3404297250&fm=26&gp=0.jpg',index:1},// {src:'/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3267295166,2381808815&fm=26&gp=0.jpg',index:2},// {src:'/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=3429654663,2972188411&fm=26&gp=0.jpg',index:3},// {src:'/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3597323878,2962972725&fm=26&gp=0.jpg',index:4},]};},components: {},computed: {},created() {},mounted() {let type = Array.isArray(this.imageList);if(!type){this.changeArr(this.imageList.url);}else{this.changeArrT(this.imageList);}},methods: {/**转格式 */changeArr(str){if(str.url == undefined){return;}let obj = {src : str.url,index : 1,show:false,other:str,}let arr = [];arr.push(obj);this.images = arr;},/**转格式 */changeArrT(arr){if(arr.length == 0){this.images=[];return;}let new_arr = [];arr.forEach((item,index)=>{let obj = {other:item,src : item.url,index : index,show:false}new_arr.push(obj);})this.images = new_arr;},//划入mouseOver(index){this.images[index].show = true;},//划出mouseLeave(index){this.images[index].show = false;},/*** 删除* */deleteImg(item){this.$emit('deleteImg',item);},},}</script><style lang='scss' scoped>.imgDiv{display: inline-block;position: relative;}.iconStyle{position: absolute;right: 10px;top: 0;width: 30px;height: 30px;font-size: 25px;text-align: center;background: rgba(0,0,0,.7);color: #fff;}</style>
二、调用方法
template:
<uploadImg></uploadImg>
js:
import uploadImg from '@/components/zdy_com/upload/uploadImg'components: {uploadImg},