亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

基于vue-upload-component封裝一個圖片上傳組件的示例

2019-11-19 12:41:29
字體:
來源:轉載
供稿:網友

需求分析

業務要求,需要一個圖片上傳控件,需滿足

  • 多圖上傳
  • 點擊預覽
  • 圖片前端壓縮
  • 支持初始化數據

相關功能及資源分析

基本功能

先到https://www.npmjs.com/search?q=vue+upload上搜索有關上傳的控件,沒有完全滿足需求的組件,過濾后找到 vue-upload-component 組件,功能基本都有,自定義也比較靈活,就以以此進行二次開發。

預覽

因為項目是基于 vant 做的,本身就提供了 ImagePreview 的預覽組件,使用起來也簡單,如果業務需求需要放大縮小,這個組件就不滿足了。

壓縮
可以通過 canvas 相關api來實現壓縮功能,還可以用一些第三方庫來實現, 例如image-compressor.js

數據

因為表單頁面涉及編輯的情況,上傳組件為了展示優雅點,需要做點處理。首先就先要對數據格式和服務端進行約定,然后在處理剩下的

開發

需求和實現思路基本確定,開始進入編碼,先搭建可運行可測試的環境

第一步,創建相關目錄

|- components |- ImageUpload |- ImageUpload.vue |- index.js

第二步,安裝依賴

$ npm i image-compressor.js -S$ npm i vue-upload-component -S

第三步,編寫核心主體代碼

// index.jsimport ImageUpload from './ImageUpload'export default ImageUpload
// ImageUpload.vue <template> <div class="m-image-upload"> <!--  這里分為兩段遍歷,理由是:在編輯情況下要默認為組件添加默認數據,雖然說組件提供了 `add` 方法,  但在編輯狀態下,需要把 url 形式的圖片轉換成 File 之后才可以添加進去,略微麻煩。  所以分兩次遍歷,一次遍歷表單對象里的圖片(直接用img標簽展示,新上傳的圖片可以通過 blob 來賦值 src),第二次遍歷組件里的 files --> <div  class="file-item"  v-for="(file, index) in value">  <img  :src="file.thumb || file.url"  @click="preview(index)"  />  <van-icon  name="clear"  class="close"  @click="remove(index, true)"/> <!-- 把圖片從數組中刪除 --> </div> <div  :class="{'file-item': true, 'active': file.active, 'error': !!file.error}"  v-for="(file, index) in files"> <!-- 加幾個樣式來控制 `上傳中` 和 `上傳失敗` 的樣式-->  <img  v-if="file.blob"  :src="file.blob"  />  <div class="uploading-shade">  <p>{{ file.progress }} %</p>  <p>正在上傳</p>  </div>  <div class="error-shade">  <p>上傳失??!</p>  </div>  <van-icon  name="clear"  class="close"  @click="remove(index)"  /> </div> <file-upload  ref="uploader"  v-model="files"  multiple  :thread="10"  extensions="jpg,gif,png,webp"  post-action="http://localhost:3000/file/upload"  @input-file="inputFile"  @input-filter="inputFilter" >  <van-icon name="photo"/> </file-upload> </div></template><script> /** * 圖片上傳控件 * 使用方法:  import ImageUpload from '@/components/ImageUpload'  ...  components: {  ImageUpload  },  ...  <image-upload :value.sync="pics"/> */ import uploader from 'vue-upload-component' import ImageCompressor from 'image-compressor.js'; import { ImagePreview } from 'vant'; export default { name: 'ImageUpload', props: {  value: Array // 通過`.sync`來添加更新值的語法題,通過 this.$emit('update:value', this.value) 來更新 }, data() {  return {  files: [] // 存放在組件的file對象  } }, components: {  'file-upload': uploader }, methods: {  // 當 add, update, remove File 這些事件的時候會觸發  inputFile(newFile, oldFile) {  // 上傳完成  if (newFile && oldFile && !newFile.active && oldFile.active) {   // 獲得相應數據   if (newFile.xhr && newFile.xhr.status === 200) {   newFile.response.data.thumb = newFile.thumb // 把縮略圖轉移   this.value.push(newFile.response.data) // 把 uploader 里的文件賦值給 value   this.$refs.uploader.remove(newFile) // 刪除當前文件對象   this.$emit('update:value', this.value) // 更新值   }  }  // 自動上傳  if (Boolean(newFile) !== Boolean(oldFile) || oldFile.error !== newFile.error) {   if (!this.$refs.uploader.active) {   this.$refs.uploader.active = true   }  }  },  // 文件過濾,可以通過 prevent 來阻止上傳  inputFilter(newFile, oldFile, prevent) {  if (newFile && (!oldFile || newFile.file !== oldFile.file)) {   // 自動壓縮   if (newFile.file && newFile.type.substr(0, 6) === 'image/') { // && this.autoCompress > 0 && this.autoCompress < newFile.size(小于一定尺寸就不壓縮)   newFile.error = 'compressing'   // 壓縮圖片   const imageCompressor = new ImageCompressor(null, {    quality: .5,    convertSize: Infinity,    maxWidth: 1000,   })   imageCompressor.compress(newFile.file).then((file) => {    // 創建 blob 字段 用于圖片預覽    newFile.blob = ''    let URL = window.URL || window.webkitURL    if (URL && URL.createObjectURL) {    newFile.blob = URL.createObjectURL(file)    }    // 縮略圖    newFile.thumb = ''    if (newFile.blob && newFile.type.substr(0, 6) === 'image/') {    newFile.thumb = newFile.blob    }    // 更新 file    this.$refs.uploader.update(newFile, {error: '', file, size: file.size, type: file.type})   }).catch((err) => {    this.$refs.uploader.update(newFile, {error: err.message || 'compress'})   })   }  }  },  remove(index, isValue) {  if (isValue) {   this.value.splice(index, 1)   this.$emit('update:value', this.value)  } else {   this.$refs.uploader.remove(this.files[index])  }  },  preview(index) {  ImagePreview({   images: this.value.map(item => (item.thumb || item.url)),   startPosition: index  });  } } }</script>

圖片壓縮也可以自己來實現,主要是理清各種文件格式的轉換

compress(imgFile) { let _this = this return new Promise((resolve, reject) => { let reader = new FileReader() reader.onload = e => {  let img = new Image()  img.src = e.target.result  img.onload = () => {  let canvas = document.createElement('canvas')  let ctx = canvas.getContext('2d')  canvas.width = img.width  canvas.height = img.height  // 鋪底色  ctx.fillStyle = '#fff'  ctx.fillRect(0, 0, canvas.width, canvas.height)  ctx.drawImage(img, 0, 0, img.width, img.height)  // 進行壓縮  let ndata = canvas.toDataURL('image/jpeg', 0.3)  resolve(_this.dataURLtoFile(ndata, imgFile.name))  } } reader.onerror = e => reject(e) reader.readAsDataURL(imgFile) })}// base64 轉 BlobdataURLtoBlob(dataurl) { let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n) while (n--) { u8arr[n] = bstr.charCodeAt(n) } return new Blob([u8arr], {type: mime})},// base64 轉 FiledataURLtoFile(dataurl, filename) { let arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n) while (n--) { u8arr[n] = bstr.charCodeAt(n) } return new File([u8arr], filename, {type: mime})}

最終效果


參考資料

vue-upload-component 文檔

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
一区二区在线视频播放| 国产精品极品在线| 欧美日韩美女在线观看| 红桃av永久久久| 亚洲精品自在久久| 成人在线激情视频| 欧美电影院免费观看| 欧美一区二区三区精品电影| 日韩一区二区福利| 亚洲成人精品视频| 亚洲欧美成人精品| 最近2019年手机中文字幕| 欧美乱大交xxxxx另类电影| 国产精品极品美女在线观看免费| 日韩视频在线免费| 国产欧美一区二区白浆黑人| 日韩精品在线第一页| 日本一区二区在线免费播放| 亚洲影影院av| 92福利视频午夜1000合集在线观看| 国产精品扒开腿做爽爽爽的视频| 日韩美女av在线免费观看| 国产精品视频白浆免费视频| 国产日本欧美一区二区三区| 国产精品视频男人的天堂| 91成品人片a无限观看| 91亚洲人电影| 日韩色av导航| 亚洲国产精品推荐| 欧美激情成人在线视频| 黄色成人在线免费| 国产精品视频专区| 久久亚洲精品中文字幕冲田杏梨| 97高清免费视频| 日韩av免费在线播放| 成人写真视频福利网| www.欧美三级电影.com| 久久精品亚洲精品| 久久精品99无色码中文字幕| 久久久久女教师免费一区| 国产xxx69麻豆国语对白| 亚洲欧美制服综合另类| 欧美成人免费在线观看| 中文字幕在线观看亚洲| 亚洲无亚洲人成网站77777| 97碰碰碰免费色视频| 国产成人精品综合久久久| 欧美激情精品久久久久久黑人| 亚洲免费av电影| 中文字幕亚洲欧美在线| 成人中文字幕在线观看| 成人xxxx视频| 欧美激情小视频| 亚洲国产精品一区二区久| 北条麻妃一区二区在线观看| 91爱爱小视频k| 国产成人亚洲综合青青| 欧美黄色片免费观看| 日韩电影免费在线观看| 国产成人在线亚洲欧美| 国产精品第三页| 久久久久久久久电影| 亚洲一二在线观看| 日韩欧美国产成人| 懂色aⅴ精品一区二区三区蜜月| 日韩成人在线电影网| 少妇高潮 亚洲精品| 性欧美办公室18xxxxhd| www.国产精品一二区| 亚洲精品一区中文| 国产精品91视频| 亚洲天堂影视av| 国产精品成人观看视频国产奇米| 久久久91精品国产| 日韩69视频在线观看| 国产成人综合精品| 97人洗澡人人免费公开视频碰碰碰| 亚洲精品日韩av| 国产精品麻豆va在线播放| 91久久嫩草影院一区二区| 久久久久女教师免费一区| 亚洲人成电影在线播放| 亚洲欧美日韩中文视频| 一区二区三区四区精品| 欧美日韩午夜剧场| 欧美一级免费看| 欧美寡妇偷汉性猛交| 亚洲第一免费网站| 在线电影欧美日韩一区二区私密| 91精品国产高清久久久久久91| 欧美日韩国产精品一区| 国产精品一二区| 丝袜一区二区三区| 欧美黑人巨大精品一区二区| 北条麻妃一区二区在线观看| 中文字幕一区二区精品| 97在线观看免费| 日韩精品视频在线播放| 国产精品老女人精品视频| 国产精品极品在线| 欧美成在线观看| 日本电影亚洲天堂| 久久久免费av| 国产精品视频久| 中文字幕亚洲图片| 国产精品aaa| 91精品久久久久久综合乱菊| 日韩精品免费在线视频| 精品国内亚洲在观看18黄| 亚洲最新av在线网站| 欧美黄色片免费观看| 成人激情视频在线观看| 欧美午夜美女看片| 欧美视频一区二区三区…| 欧美中文字幕第一页| 91性高湖久久久久久久久_久久99| 亚洲人成在线免费观看| 欧美成人免费va影院高清| 日韩在线视频免费观看| 国产午夜精品视频| 国产精品美腿一区在线看| 亚洲精品影视在线观看| 最近2019中文字幕在线高清| 日日骚av一区| 欧美洲成人男女午夜视频| 久久噜噜噜精品国产亚洲综合| 77777亚洲午夜久久多人| 色综合伊人色综合网| 欧美激情视频在线观看| 欧美性色19p| 亚洲成人久久网| 在线观看91久久久久久| 精品无人区乱码1区2区3区在线| 精品动漫一区二区| 日韩美女视频在线观看| 亚洲欧洲美洲在线综合| 91av视频在线免费观看| 韩国一区二区电影| 亚洲一区二区久久久久久| 91精品国产91久久久久久最新| 青青草一区二区| 国产精品亚洲网站| 成人精品在线视频| 国产精品久久久久免费a∨大胸| 亚洲精品久久7777777| 亚洲欧美日韩国产中文| 日韩大胆人体377p| 亚洲国产天堂久久综合| 国产视频一区在线| 色狠狠av一区二区三区香蕉蜜桃| 国产999在线观看| 日本欧美中文字幕| 精品久久久久久中文字幕| 国产成人精品综合久久久| 亚洲精品成人av| 热门国产精品亚洲第一区在线| 亚洲欧洲日产国码av系列天堂| 日韩在线播放视频| 欧美夫妻性视频| 懂色aⅴ精品一区二区三区蜜月| 久久精品电影网| 欧美激情久久久久| 日韩欧美国产免费播放| www国产亚洲精品久久网站|