解讀vant的Uploader上傳問(wèn)題
vant的Uploader上傳
vant的uploader組件的交互是點(diǎn)擊上傳之后才會(huì)觸發(fā)一系列回調(diào)函數(shù),如果想要實(shí)現(xiàn)點(diǎn)擊uploader的時(shí)候先出現(xiàn)彈框提示,選擇了確定之后才進(jìn)行文件上傳這該怎么做到呢?
大致是,給uploader組件外面包裹一層元素,然后給組件設(shè)為禁用模式,當(dāng)外層的元素狀態(tài)改變時(shí),就改變組件的disabled值,再使用vant提供的chooseFile通過(guò) ref 可以獲取到 Uploader 實(shí)例并調(diào)用實(shí)例的方法重新調(diào)起文件選擇。
主要的步驟如下
首先,我們可以在uploader組件外面包裹一層div
?? ?<span ? ? ? @click="handleClick" ? ? ? v-if="isconfirm" ? ? ? class="message" ? ? ></span> ? ? <van-uploader ? ? ? v-model="fileList" ? ? ? :after-read="afterRead" ? ? ? :disabled="isconfirm" ? ? ? ref="uploadImg" ? ? />
然后在data以及methods中進(jìn)行定義
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這個(gè)方法支持的版本是v2.5.6以上的,如果出現(xiàn)了沒(méi)有效果的話(huà),先檢查一下自己安裝的版本是否是符合要求的。
檢查之后,版本也符合要求,但是this.$refs.uploadImg.chooseFile()就是沒(méi)有效果,這是怎么一回事呢?
原來(lái)跟瀏覽器執(zhí)行機(jī)制event loop有關(guān),每當(dāng)執(zhí)行到choosefile的時(shí)候,組件仍為禁用模式,無(wú)法調(diào)起,其實(shí)isconfirm狀態(tài)還沒(méi)有進(jìn)行改變,所以調(diào)起文件選擇看不見(jiàn)效果,可以使用一個(gè)setTimeout或者是vue中的this.$nextTick()進(jìn)行解決。
setTimeout(() => { ? ? this.$refs.uploadImg.chooseFile(); ?}, 0); ? this.$nextTick(() => { ??? ?this.$refs.uploadImg.chooseFile(); });
vant文件上傳Uploader圖片壓縮
為什么要對(duì)圖片進(jìn)行壓縮?
隨著科技的發(fā)展,手機(jī)像素越來(lái)越好,拍攝的圖片也越來(lái)越清晰。圖片越清晰,體積也就越大。當(dāng)移動(dòng)端上傳大圖時(shí)就會(huì)發(fā)生卡頓,請(qǐng)求超時(shí)的情況。
當(dāng)圖片過(guò)大時(shí),圖片預(yù)覽也會(huì)非常慢,所以需要在圖片上傳時(shí)對(duì)圖片進(jìn)行壓縮。
vant中文件上傳組件Uploader并不支持圖片壓縮,因?yàn)闃I(yè)務(wù)場(chǎng)景中有多個(gè)地方需要上傳圖片時(shí)對(duì)圖片進(jìn)行壓縮,所以我基于Uploader封裝了一個(gè)新的組件。
Uploader組件封裝
此組件封裝 基于vant文件上傳Uploader
API
屬性名 | 屬性說(shuō)明 | 默認(rèn)值 |
---|---|---|
quality | 壓縮質(zhì)量【0-1】 | 0.5 |
compressSwitch | 是否開(kāi)啟壓縮 | false |
threshold | 達(dá)到此大小開(kāi)始?jí)嚎s【500k】 | 500 |
Vant 文件上傳Uploader屬性請(qǐng)參照 vant官網(wǎng)
模板部分
<template> ? ? <van-uploader :fileList="$attrs.value" :before-read="beforeReadFn" v-bind="$attrs" v-on="$listeners"/> </template>
Javascript部分
export default { ? 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('處理圖片F(xiàn)n...'); ? ? ? let self = this ? ? ? // 看支持不支持FileReader ? ? ? if (!file || !window.FileReader) return; ? ? ? const size = file.size/1024 ? ? ? console.log(`圖片大小 ===> ${file.size/1024}k`); ? ? ? console.log('圖片壓縮:',this.compressSwitch?'開(kāi)':'關(guān)'); ? ? ? console.log('圖片壓縮閾值:',this.threshold+'k'); ? ? ? console.log('圖片壓縮降幀值:',this.quality); ? ? ? if (/^image/.test(file.type) && size >= this.threshold && this.compressSwitch) { ? ? ? ? // 創(chuàng)建一個(gè)reader ? ? ? ? let reader = new FileReader() ? ? ? ? // 將圖片2將轉(zhuǎn)成 base64 格式 ? ? ? ? reader.readAsDataURL(file) ? ? ? ? // 讀取成功后的回調(diào) ? ? ? ? reader.onloadend = function() { ? ? ? ? ? let result = this.result ? ? ? ? ? let img = new Image() ? ? ? ? ? img.src = result ? ? ? ? ? img.onload = function() { ? ? ? ? ? ? // 壓縮 ? ? ? ? ? ? let data = self.compress(img,file.name,file.type) ? ? ? ? ? ? console.log(`壓縮后 ===>${data.fileData.size/1024}k`); ? ? ? ? ? ? self.$attrs.value[index].content = data.base64Data ? ? ? ? ? ? self.$attrs.value[index].file = data.fileData ? ? ? ? ? } ? ? ? ? } ? ? ? } ? ? }, ? ? // 壓縮圖片 ? ? compress(img, name, type) { ? ? ? let canvas = document.createElement('canvas') ? ? ? let ctx = canvas.getContext('2d') ? ? ? //瓦片canvas ? ? ? let tCanvas = document.createElement('canvas') ? ? ? let tctx = tCanvas.getContext('2d') ? ? ? // let initSize = img.src.length; ? ? ? let width = img.width ? ? ? let height = img.height ? ? ? //如果圖片大于四百萬(wàn)像素,計(jì)算壓縮比并將大小壓至400萬(wàn)以下 ? ? ? let ratio ? ? ? if ((ratio = (width * height) / 4000000) > 1) { ? ? ? ? // console.log("大于400萬(wàn)像素"); ? ? ? ? ratio = Math.sqrt(ratio) ? ? ? ? width /= ratio ? ? ? ? height /= ratio ? ? ? } else { ? ? ? ? ratio = 1 ? ? ? } ? ? ? canvas.width = width ? ? ? canvas.height = height ? ? ? // ? ?鋪底色 ? ? ? ctx.fillStyle = '#fff' ? ? ? ctx.fillRect(0, 0, canvas.width, canvas.height) ? ? ? //如果圖片像素大于100萬(wàn)則使用瓦片繪制 ? ? ? let count ? ? ? if ((count = (width * height) / 1000000) > 1) { ? ? ? ? // console.log("超過(guò)100W像素"); ? ? ? ? count = ~~(Math.sqrt(count) + 1) //計(jì)算要分成多少塊瓦片 ? ? ? ? // ? ? ?計(jì)算每塊瓦片的寬和高 ? ? ? ? let nw = ~~(width / count) ? ? ? ? let nh = ~~(height / count) ? ? ? ? tCanvas.width = nw ? ? ? ? tCanvas.height = nh ? ? ? ? for (let i = 0; i < count; i++) { ? ? ? ? ? for (let j = 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) ? ? ? } ? ? ? //進(jìn)行壓縮? ? ? ? let ndata = 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轉(zhuǎn)換為文件 ? ? dataURLtoFile(dataurl,name,type) { ? ? ? name = name ? name : '圖片' ? ? ? type = type ? type : 'jpg' ? ? ? var arr = dataurl.split(','), ? ? ? ? bstr = atob(arr[1]), ? ? ? ? n = bstr.length, ? ? ? ? u8arr = new Uint8Array(n) ? ? ? while (n--) { ? ? ? ? u8arr[n] = bstr.charCodeAt(n) ? ? ? } ? ? ? return new File([u8arr], name, { ? ? ? ? type: type ? ? ? }) ? ? }, ? ? beforeReadFn(file,detail){ ? ? ? const {index} = detail ? ? ? this.imgPreview(file,index) ? ? ? return this.beforeRead(...arguments); ? ? } ? }, ? mounted(){ ? ?? ? } };
使用示例
<SmUpload v-model="fileList" :before-read="beforeRead" :compressSwitch="true" :quality="0.5"/>
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue2.0實(shí)現(xiàn)點(diǎn)擊其他區(qū)域關(guān)閉自定義div功能
這篇文章主要介紹了vue2.0實(shí)現(xiàn)點(diǎn)擊其他區(qū)域關(guān)閉自定義div功能實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06淺談vue同一頁(yè)面中擁有兩個(gè)表單時(shí),的驗(yàn)證問(wèn)題
今天小編就為大家分享一篇淺談vue同一頁(yè)面中擁有兩個(gè)表單時(shí),的驗(yàn)證問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-09-09關(guān)于Element-ui中table默認(rèn)選中toggleRowSelection問(wèn)題
這篇文章主要介紹了關(guān)于Element-ui中table默認(rèn)選中toggleRowSelection問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08vue+element搭建后臺(tái)小總結(jié) el-dropdown下拉功能
這篇文章主要為大家詳細(xì)介紹了vue+element搭建后臺(tái)小總結(jié),el-dropdown下拉功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09利用Vue3和element-plus實(shí)現(xiàn)圖片上傳組件
element-plus提供了uploader組件,但是不好定制化。所以本文將利用Vue3和element-plus實(shí)現(xiàn)一個(gè)圖片上傳的組件,感興趣的可以了解一下2022-03-03Vue--Router動(dòng)態(tài)路由的用法示例詳解
這篇文章主要介紹了Vue--Router動(dòng)態(tài)路由的用法,很多時(shí)候,我們需要將給定匹配模式的路由映射到同一個(gè)組件,在?Vue?Router?中,我們可以在路徑中使用一個(gè)動(dòng)態(tài)字段來(lái)實(shí)現(xiàn),我們稱(chēng)之為路徑參數(shù),本文對(duì)Vue?Router動(dòng)態(tài)路由相關(guān)知識(shí)給大家介紹的非常詳細(xì),需要的朋友參考下吧2022-08-08