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

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

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

需求分析

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

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

相關(guān)功能及資源分析

基本功能

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

預(yù)覽

因?yàn)轫?xiàng)目是基于 vant 做的,本身就提供了 ImagePreview 的預(yù)覽組件,使用起來(lái)也簡(jiǎn)單,如果業(yè)務(wù)需求需要放大縮小,這個(gè)組件就不滿足了。

壓縮
可以通過(guò) canvas 相關(guān)api來(lái)實(shí)現(xiàn)壓縮功能,還可以用一些第三方庫(kù)來(lái)實(shí)現(xiàn), 例如image-compressor.js

數(shù)據(jù)

因?yàn)楸韱雾?yè)面涉及編輯的情況,上傳組件為了展示優(yōu)雅點(diǎn),需要做點(diǎn)處理。首先就先要對(duì)數(shù)據(jù)格式和服務(wù)端進(jìn)行約定,然后在處理剩下的

開(kāi)發(fā)

需求和實(shí)現(xiàn)思路基本確定,開(kāi)始進(jìn)入編碼,先搭建可運(yùn)行可測(cè)試的環(huán)境

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

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

第二步,安裝依賴

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

第三步,編寫(xiě)核心主體代碼

// index.js
import ImageUpload from './ImageUpload'
export default ImageUpload
// ImageUpload.vue 
<template>
 <div class="m-image-upload">
 <!--
  這里分為兩段遍歷,理由是:在編輯情況下要默認(rèn)為組件添加默認(rèn)數(shù)據(jù),雖然說(shuō)組件提供了 `add` 方法,
  但在編輯狀態(tài)下,需要把 url 形式的圖片轉(zhuǎn)換成 File 之后才可以添加進(jìn)去,略微麻煩。
  所以分兩次遍歷,一次遍歷表單對(duì)象里的圖片(直接用img標(biāo)簽展示,新上傳的圖片可以通過(guò) blob 來(lái)賦值 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"> <!-- 加幾個(gè)樣式來(lái)控制 `上傳中` 和 `上傳失敗` 的樣式-->
  <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 // 通過(guò)`.sync`來(lái)添加更新值的語(yǔ)法題,通過(guò) this.$emit('update:value', this.value) 來(lái)更新
 },
 data() {
  return {
  files: [] // 存放在組件的file對(duì)象
  }
 },
 components: {
  'file-upload': uploader
 },
 methods: {
  // 當(dāng) add, update, remove File 這些事件的時(shí)候會(huì)觸發(fā)
  inputFile(newFile, oldFile) {
  // 上傳完成
  if (newFile && oldFile && !newFile.active && oldFile.active) {
   // 獲得相應(yīng)數(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) // 刪除當(dāng)前文件對(duì)象
   this.$emit('update:value', this.value) // 更新值
   }
  }

  // 自動(dòng)上傳
  if (Boolean(newFile) !== Boolean(oldFile) || oldFile.error !== newFile.error) {
   if (!this.$refs.uploader.active) {
   this.$refs.uploader.active = true
   }
  }
  },
  // 文件過(guò)濾,可以通過(guò) prevent 來(lái)阻止上傳
  inputFilter(newFile, oldFile, prevent) {
  if (newFile && (!oldFile || newFile.file !== oldFile.file)) {
   // 自動(dòng)壓縮
   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 字段 用于圖片預(yù)覽
    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>

圖片壓縮也可以自己來(lái)實(shí)現(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)

  // 進(jìn)行壓縮
  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 文檔

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

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

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

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

    詳細(xì)聊聊vue中組件的props屬性

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

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

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

    Vue.js中使用道具方法demo

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

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

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

    Vue 實(shí)現(xiàn)高級(jí)穿梭框 Transfer 封裝過(guò)程

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

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

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

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

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

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

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

    vue的rules驗(yàn)證部分可以部分又失效的原因及解決方案

    vue的rules驗(yàn)證失效,部分可以部分又失效,很多百度都有,但是我這里遇到了一個(gè)特別的,那就是prop沒(méi)有寫(xiě)全,導(dǎo)致驗(yàn)證某一個(gè)失效,接下來(lái)就跟小編一起來(lái)看看這個(gè)失效的原因和解決方案吧
    2023-11-11

最新評(píng)論