欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2018年10月16日 14:13:40   作者:拳頭巴掌  
這篇文章主要介紹了基于vue-upload-component封裝一個圖片上傳組件的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

需求分析

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

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

相關功能及資源分析

基本功能

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

預覽

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

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

數(shù)據(jù)

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

開發(fā)

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

第一步,創(chuàng)建相關目錄

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

第二步,安裝依賴

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

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

// index.js
import ImageUpload from './ImageUpload'
export default ImageUpload
// ImageUpload.vue 
<template>
 <div class="m-image-upload">
 <!--
  這里分為兩段遍歷,理由是:在編輯情況下要默認為組件添加默認數(shù)據(jù),雖然說組件提供了 `add` 方法,
  但在編輯狀態(tài)下,需要把 url 形式的圖片轉(zhuǎn)換成 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)"/> <!-- 把圖片從數(shù)組中刪除 -->
 </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 這些事件的時候會觸發(fā)
  inputFile(newFile, oldFile) {
  // 上傳完成
  if (newFile && oldFile && !newFile.active && oldFile.active) {
   // 獲得相應數(shù)據(jù)
   if (newFile.xhr && newFile.xhr.status === 200) {
   newFile.response.data.thumb = newFile.thumb // 把縮略圖轉(zhuǎn)移
   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) => {
    // 創(chuàng)建 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>

圖片壓縮也可以自己來實現(xiàn),主要是理清各種文件格式的轉(zhuǎn)換

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 轉(zhuǎn) Blob
dataURLtoBlob(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 轉(zhuǎn) File
dataURLtoFile(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 文檔

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • 在Vue3中使用CSS Modules實現(xiàn)樣式隔離

    在Vue3中使用CSS Modules實現(xiàn)樣式隔離

    隨著構建現(xiàn)代前端應用的需要,樣式的管理和隔離變得越來越重要,為了解決樣式?jīng)_突和管理困難的問題,CSS Modules 應運而生,本文我們將討論如何在 Vue3 中使用 CSS Modules 實現(xiàn)樣式隔離,需要的朋友可以參考下
    2024-09-09
  • 詳細聊聊vue中組件的props屬性

    詳細聊聊vue中組件的props屬性

    父子組件之間的通信就是props down,events up,父組件通過屬性props向下傳遞數(shù)據(jù)給子組件,子組件通過事件events 給父組件發(fā)送消息,這篇文章主要給大家介紹了關于vue中組件的props屬性的相關資料,需要的朋友可以參考下
    2021-11-11
  • vue-cli2.0轉(zhuǎn)3.0之項目搭建的詳細步驟

    vue-cli2.0轉(zhuǎn)3.0之項目搭建的詳細步驟

    這篇文章主要介紹了vue-cli2.0轉(zhuǎn)3.0之項目搭建的詳細步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • Vue.js中使用道具方法demo

    Vue.js中使用道具方法demo

    這篇文章主要為大家介紹了Vue.js中使用道具方法demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • Vue中ref、reactive、toRef、toRefs、$refs的基本用法總結

    Vue中ref、reactive、toRef、toRefs、$refs的基本用法總結

    這篇文章主要給大家介紹了關于Vue中ref、reactive、toRef、toRefs、$refs的基本用法,以及他們之家的區(qū)別,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-11-11
  • Vue 實現(xiàn)高級穿梭框 Transfer 封裝過程

    Vue 實現(xiàn)高級穿梭框 Transfer 封裝過程

    本文介紹了基于Vue2和Element-UI實現(xiàn)的高級穿梭框組件Transfer的設計與技術方案,組件支持多項選擇,并能實時同步已選擇項,包含豎版和橫版設計稿,并提供了組件的使用方法和源碼,此組件具備本地分頁和搜索功能,適用于需要在兩個列表間進行數(shù)據(jù)選擇和同步的場景
    2024-09-09
  • el-table嵌套el-popover處理卡頓的解決

    el-table嵌套el-popover處理卡頓的解決

    本文主要介紹了el-table嵌套el-popover處理卡頓的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-05-05
  • 淺談vue的props,data,computed變化對組件更新的影響

    淺談vue的props,data,computed變化對組件更新的影響

    本篇文章主要介紹了淺談vue的props,data,computed變化對組件更新的影響,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • vue實現(xiàn)上傳圖片添加水印

    vue實現(xiàn)上傳圖片添加水印

    這篇文章主要為大家詳細介紹了vue實現(xiàn)上傳圖片添加水印,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • vue的rules驗證部分可以部分又失效的原因及解決方案

    vue的rules驗證部分可以部分又失效的原因及解決方案

    vue的rules驗證失效,部分可以部分又失效,很多百度都有,但是我這里遇到了一個特別的,那就是prop沒有寫全,導致驗證某一個失效,接下來就跟小編一起來看看這個失效的原因和解決方案吧
    2023-11-11

最新評論