最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

需求分析

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

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

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

基本功能

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

預(yù)覽

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

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

數(shù)據(jù)

因?yàn)楸韱雾撁嫔婕熬庉嫷那闆r,上傳組件為了展示優(yōu)雅點(diǎn),需要做點(diǎn)處理。首先就先要對(duì)數(shù)據(jù)格式和服務(wù)端進(jìn)行約定,然后在處理剩下的

開發(fā)

需求和實(shí)現(xiàn)思路基本確定,開始進(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

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

// index.js
import ImageUpload from './ImageUpload'
export default ImageUpload
// ImageUpload.vue 
<template>
 <div class="m-image-upload">
 <!--
  這里分為兩段遍歷,理由是:在編輯情況下要默認(rèn)為組件添加默認(rèn)數(shù)據(jù),雖然說組件提供了 `add` 方法,
  但在編輯狀態(tài)下,需要把 url 形式的圖片轉(zhuǎn)換成 File 之后才可以添加進(jìn)去,略微麻煩。
  所以分兩次遍歷,一次遍歷表單對(duì)象里的圖片(直接用img標(biāo)簽展示,新上傳的圖片可以通過 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"> <!-- 加幾個(gè)樣式來控制 `上傳中` 和 `上傳失敗` 的樣式-->
  <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對(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
   }
  }
  },
  // 文件過濾,可以通過 prevent 來阻止上傳
  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>

圖片壓縮也可以自己來實(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)文章

  • Vue 2.5 Level E 發(fā)布了: 新功能特性一覽

    Vue 2.5 Level E 發(fā)布了: 新功能特性一覽

    很高興Vue 2.5 Level E 發(fā)布了。在這篇文章中,我們將重點(diǎn)介紹一些更重要的的變化:更好的 TypeScript 集成,更好的錯(cuò)誤處理,更好地支持單文件組件中的函數(shù)式組件以及與環(huán)境無關(guān)的服務(wù)端渲染
    2017-10-10
  • vue.js項(xiàng)目nginx部署教程

    vue.js項(xiàng)目nginx部署教程

    nginx是一個(gè)高性能的HTTP和反向代理服務(wù)器。這篇文章主要介紹了vue.js項(xiàng)目nginx部署,需要的朋友可以參考下
    2018-04-04
  • Vue項(xiàng)目的表單校驗(yàn)實(shí)戰(zhàn)指南

    Vue項(xiàng)目的表單校驗(yàn)實(shí)戰(zhàn)指南

    這篇文章主要介紹了Vue項(xiàng)目表單校驗(yàn)的相關(guān)資料,前端表單校驗(yàn)?zāi)軠p少無效請(qǐng)求,保護(hù)后端接口,使用ElementPlus表單組件進(jìn)行校驗(yàn),需要準(zhǔn)備表單對(duì)象、規(guī)則對(duì)象并進(jìn)行雙向綁定,用戶名、密碼以及協(xié)議勾選等字段都需符合特定規(guī)則,需要的朋友可以參考下
    2024-10-10
  • 詳解Vue-基本標(biāo)簽和自定義控件

    詳解Vue-基本標(biāo)簽和自定義控件

    本篇文章主要介紹了Vue-基本標(biāo)簽和自定義控件,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • vue如何添加jest測(cè)試

    vue如何添加jest測(cè)試

    這篇文章主要介紹了vue如何添加jest測(cè)試問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • vue3自定義hooks/可組合函數(shù)方式

    vue3自定義hooks/可組合函數(shù)方式

    這篇文章主要介紹了vue3自定義hooks/可組合函數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Vue2安裝使用MonacoEditor方式(自定義語法,自定義高亮,自定義提示)

    Vue2安裝使用MonacoEditor方式(自定義語法,自定義高亮,自定義提示)

    這篇文章主要介紹了Vue2安裝使用MonacoEditor方式(自定義語法,自定義高亮,自定義提示),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • 深入理解vue-loader如何使用

    深入理解vue-loader如何使用

    本篇文章主要介紹了vue-loader,vue-loader是webpack下loader插件 可以把.vue文件輸出成組件,有興趣的可以了解一下
    2017-06-06
  • Ant?Design?Vue中的table與pagination的聯(lián)合使用方式

    Ant?Design?Vue中的table與pagination的聯(lián)合使用方式

    這篇文章主要介紹了Ant?Design?Vue中的table與pagination的聯(lián)合使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 初識(shí) Vue.js 中的 *.Vue文件

    初識(shí) Vue.js 中的 *.Vue文件

    vue.js是一套構(gòu)建用戶界面的漸進(jìn)式框架,它采用自底向上增量開發(fā)的設(shè)計(jì).這篇文章主要介紹了VueJs 填坑日記之初識(shí) *.Vue文件,需要的朋友可以參考下
    2017-11-11

最新評(píng)論

曲麻莱县| 砚山县| 彭阳县| 中阳县| 康乐县| 丰顺县| 乌兰察布市| 合肥市| 通许县| 临沧市| 丘北县| 凤山县| 台南县| 含山县| 衢州市| 扬中市| 江阴市| 大庆市| 旅游| 门头沟区| 杭锦后旗| 南涧| 集贤县| 明星| 呼玛县| 彰武县| 新宾| 囊谦县| 嵊州市| 会理县| 满洲里市| 琼结县| 仪征市| 沾益县| 任丘市| 南召县| 乌拉特前旗| 亳州市| 绥德县| 平江县| 兴化市|