1987WEB视界-分享互联网热点话题和事件

您现在的位置是:首页 > WEB开发 > 正文

WEB开发

解读vant的Uploader上传问题

1987web2024-03-25WEB开发41
这篇文章主要介绍了解读vant的Uploader上传问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

这篇文章主要介绍了解读vant的Uploader上传问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

vant的Uploader上传

vant的uploader组件的交互是点击上传之后才会触发一系列回调函数,如果想要实现点击uploader的时候先出现弹框提示,选择了确定之后才进行文件上传这该怎么做到呢?

大致是,给uploader组件外面包裹一层元素,然后给组件设为禁用模式,当外层的元素状态改变时,就改变组件的disabled值,再使用vant提供的chooseFile通过 ref 可以获取到 Uploader 实例并调用实例的方法重新调起文件选择。

主要的步骤如下

首先,我们可以在uploader组件外面包裹一层div

@click="handleClick"v-if="isconfirm"class="message"> v-model="fileList":after-read="afterRead":disabled="isconfirm"ref="uploadImg"/>

然后在data以及methods中进行定义

data(){return{fileList:[],isconfirm:true};methods:{handleClick(){this.$dialog.confirm({message:"test,test,test"}).then(()=>{this.isconfirm=false;this.$refs.uploadImg.chooseFile();}).catch(()=>{this.isconfirm=true;});},}

看到这里要注意chooseFile这个方法支持的版本是v2.5.6以上的,如果出现了没有效果的话,先检查一下自己安装的版本是否是符合要求的。

检查之后,版本也符合要求,但是this.$refs.uploadImg.chooseFile()就是没有效果,这是怎么一回事呢?

原来跟浏览器执行机制event loop有关,每当执行到choosefile的时候,组件仍为禁用模式,无法调起,其实isconfirm状态还没有进行改变,所以调起文件选择看不见效果,可以使用一个setTimeout或者是vue中的this.$nextTick()进行解决。

setTimeout(()=>{this.$refs.uploadImg.chooseFile();},0);this.$nextTick(()=>{this.$refs.uploadImg.chooseFile();});

vant文件上传Uploader图片压缩

为什么要对图片进行压缩?

随着科技的发展,手机像素越来越好,拍摄的图片也越来越清晰。图片越清晰,体积也就越大。当移动端上传大图时就会发生卡顿,请求超时的情况。

当图片过大时,图片预览也会非常慢,所以需要在图片上传时对图片进行压缩。

vant中文件上传组件Uploader并不支持图片压缩,因为业务场景中有多个地方需要上传图片时对图片进行压缩,所以我基于Uploader封装了一个新的组件。

Uploader组件封装

此组件封装 基于vant文件上传Uploader

API

属性名属性说明默认值

quality

压缩质量【0-1】0.5

compressSwitch

是否开启压缩false

threshold

达到此大小开始压缩【500k】500

Vant 文件上传Uploader属性请参照 vant官网

模板部分

: fileList="$attrs.value":before-read="beforeReadFn"v-bind="$attrs"v-on="$listeners"/>

Javascript部分

exportdefault{name:van-small-upload,props:{quality:{type:Number,default:0.1},compressSwitch:{type:Boolean,default:false},threshold:{type:Number,default:500},beforeRead:{type:Function,default:()=>true}},data(){return{}},methods:{// 处理图片imgPreview(file,index){console.log(处理图片Fn...);letself=this// 看支持不支持FileReaderif(!file||!window.FileReader)return;constsize=file.size/1024console.log(`图片大小 ===> ${file.size/1024}k`);console.log(图片压缩:,this.compressSwitch?:);console.log(图片压缩阈值:,this.threshold+k);console.log(图片压缩降帧值:,this.quality);if(/^image/.test(file.type)&&size>=this.threshold&&this.compressSwitch){// 创建一个readerletreader=newFileReader()// 将图片2将转成 base64 格式reader.readAsDataURL(file)// 读取成功后的回调reader.onloadend=function(){letresult=this.resultletimg=newImage()img.src=resultimg.onload=function(){// 压缩letdata=self.compress(img,file.name,file.type)console.log(`压缩后 ===>${data.fileData.size/1024}k`);self.$attrs.value[index].content=data.base64Dataself.$attrs.value[index].file=data.fileData}}}},// 压缩图片compress(img,name,type){letcanvas=document.createElement(canvas)letctx=canvas.getContext(2d)//瓦片canvaslettCanvas=document.createElement(canvas)lettctx=tCanvas.getContext(2d)// let initSize = img.src.length;letwidth=img.widthletheight=img.height//如果图片大于四百万像素,计算压缩比并将大小压至400万以下letratioif((ratio=(width*height)/4000000)>1){// console.log("大于400万像素");ratio=Math.sqrt(ratio)width/=ratioheight/=ratio}else{ratio=1}canvas.width=widthcanvas.height=height//    铺底色ctx.fillStyle=#fffctx.fillRect(0,0,canvas.width,canvas.height)//如果图片像素大于100万则使用瓦片绘制letcountif((count=(width*height)/1000000)>1){// console.log("超过100W像素");count=~~(Math.sqrt(count)+1)//计算要分成多少块瓦片//      计算每块瓦片的宽和高letnw=~~(width/count)letnh=~~(height/count)tCanvas.width=nwtCanvas.height=nhfor(leti=0;i<count;i++){for(letj=0;j<count;j++){tctx.drawImage(img,i*nw*ratio,j*nh*ratio,nw*ratio,nh*ratio,0,0,nw,nh)ctx.drawImage(tCanvas,i*nw,j*nh,nw,nh)}}}else{ctx.drawImage(img,0,0,width,height)}//进行压缩letndata=canvas.toDataURL(image/jpeg,this.quality)tCanvas.width=tCanvas.height=canvas.width=canvas.height=0;return{base64Data:ndata,fileData:this.dataURLtoFile(ndata,name,type)}},//将base64转换为文件dataURLtoFile(dataurl,name,type){name=name?name:图片type=type?type:jpgvararr=dataurl.split(,),bstr=atob(arr[1]),n=bstr.length,u8arr=newUint8Array(n)while(n--){u8arr[n]=bstr.charCodeAt(n)}returnnewFile([u8arr],name,{type:type})},beforeReadFn(file,detail){const{index}=detailthis.imgPreview(file,index)returnthis.beforeRead(...arguments);}},mounted(){}};

使用示例

v-model="fileList":before-read="beforeRead":compressSwitch="true":quality="0.5"/>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持本站。

声明:本站所有文章,如无特殊说明或标注,均为爬虫抓取以及网友投稿,版权归原作者所有。