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

Vue的移動(dòng)端多圖上傳插件vue-easy-uploader的示例代碼

 更新時(shí)間:2017年11月27日 11:48:18   作者:小昱博客  
這篇文章主要介紹了Vue的移動(dòng)端多圖上傳插件vue-easy-uploader的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

前言

這段時(shí)間趕項(xiàng)目,需要用到多文件上傳,用Vue進(jìn)行前端項(xiàng)目開(kāi)發(fā)。在網(wǎng)上找了不少插件,都不是十分滿意,有的使用起來(lái)繁瑣,有的不能適應(yīng)本項(xiàng)目。就打算自己折騰一下,寫一個(gè)Vue的上傳插件,一勞永逸,以后可以直接使用。

目前vue-easy-uploader已上傳到GitHub和NPM,使用起來(lái)方便簡(jiǎn)單,不需要繁瑣的配置即可投入生產(chǎn),不過(guò)需要后端配合,實(shí)現(xiàn)上傳接口。

本項(xiàng)目GitHub地址: https://github.com/quanzaiyu/vue-easy-uploader

本項(xiàng)目NPM地址: https://www.npmjs.com/package/vue-easy-uploader

詳細(xì)的使用方法都在倉(cāng)庫(kù)Readme中,就不贅述,這里談下本插件的設(shè)計(jì)開(kāi)發(fā)思路。

插件介紹

vue-easy-uploader是一個(gè)多圖上傳插件。主要特性包括:

  1. 多文件上傳
  2. 上傳圖片預(yù)覽
  3. 上傳狀態(tài)監(jiān)測(cè)
  4. 刪除指定圖片
  5. 清空?qǐng)D片
  6. 重新上傳

后期版本迭代將不限于圖片,往通用文件上傳進(jìn)行改進(jìn)。

先看看上傳插件使用時(shí)候的效果圖:


目錄結(jié)構(gòu)


index.js # 主入口文件
store.js # 狀態(tài)管理
uploader.vue # 上傳組件

文件解析

index.js

import uploader from './uploader'
import store from './store'

let plugin = {}

plugin.install = function (_Vue, _store) {
 _Vue.component('uploader', uploader)
 _store.registerModule('imgstore', store)
}

export default plugin

這是插件的主入口文件,注冊(cè)了全局的上傳組件和狀態(tài)管理,使用時(shí)只需要在項(xiàng)目入口文件(一般是main.js)中加入以下代碼即可引入此插件:

import Vue from 'vue'
import Vuex from 'vuex'
import uploader from 'vue-easy-uploader'
 
let store = new Vuex.Store({})
Vue.use(uploader, store)

store.js

此文件為狀態(tài)管理配置文件,主要包含三個(gè)state:

img_upload_cache # 上傳文件緩存
img_paths # 上傳狀態(tài),包括 ready selected uploading finished
img_status # 上傳后的路徑反饋數(shù)組(數(shù)據(jù)結(jié)構(gòu)為Set集合)

針對(duì)每個(gè)state都有自己的mutation,用于改變state,規(guī)范上mutation都需要使用大寫字母加下劃線的形式,本人習(xí)慣使用小寫字母,不過(guò)都不是原則上的問(wèn)題。

最重要的一個(gè)state是img_status,用于監(jiān)視圖片上傳的狀態(tài)。包括以下幾個(gè)狀態(tài):

ready # 上傳開(kāi)始前的準(zhǔn)備狀態(tài) 
selected # 已選擇上傳文件 
uploading # 開(kāi)始上傳 
finished # 上傳完畢 

在組件中可以通過(guò)改變上傳狀態(tài)實(shí)現(xiàn)文件的上傳,同時(shí)也可以監(jiān)聽(tīng)上傳狀態(tài)的變化而執(zhí)行回調(diào)。如:

methods: {
 upload () {
  this.$store.commit('set_img_status', 'uploading')
 },
 submit () {
  // some code
 }
}
computed: {
 ...mapState({
  imgStatus: state => state.imgstore.img_status
 })
},
watch: {
 imgStatus () {
  if (this.imgStatus === 'finished') {
   this.submit()
  }
 }
}

上述代碼中,使用upload方法更新了上傳狀態(tài),讓圖片開(kāi)始執(zhí)行上傳操作,使用watch進(jìn)行上傳狀態(tài)的監(jiān)視,當(dāng)上傳完成(img_status狀態(tài)變?yōu)閒inished),執(zhí)行回調(diào)函數(shù)submit。

源文件如下:

// Created by quanzaiyu on 2017/10/25 0025.
var state = {
 img_upload_cache: [],
 img_paths: [],
 img_status: 'ready' // 上傳狀態(tài) ready selected uploading finished
}

const actions = {}

const getters = {}

const mutations = {
 set_img_upload_cache (state, arg) {
  state.img_upload_cache = arg
 },
 set_img_paths (state, arg) {
  state.img_paths = arg
 },
 set_img_status (state, arg) {
  state.img_status = arg
 }
}

export default {
 state,
 mutations,
 actions,
 getters
}

uploader.vue

先看源代碼(為了節(jié)省空間,未貼出style部分的代碼):

<template>
 <div class="imgUploader">
  <div class="file-list">
   <section
    v-for="(file, index) in imgStore" :key="index"
    class="file-item draggable-item"
   >
    <img :src="file.src" alt="" ondragstart="return false;">
    <span class="file-remove" @click="remove(index)">+</span>
   </section>
   <section class="file-item" v-if="imgStatus !== 'finished'">
    <div class="add">
     <span>+</span>
     <input type="file" pictype='30010003' multiple
      data-role="none" accept="image/*"
      @change="selectImgs"
      ref="file"
     >
    </div>
   </section>
  </div>
  <div class="uploadBtn">
   <section>
    <span v-if="imgStore.length > 0" class="empty"
     @click="empty">
      {{imgStatus === 'finished' ? '重新上傳' : '清空'}}
    </span>
   </section>
  </div>
 </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
 props: ['url'],
 data () {
  return {
   files: [], // 文件緩存
   index: 0 // 序列號(hào)
  }
 },
 computed: {
  ...mapState({
   imgStore: state => state.imgstore.img_upload_cache,
   imgPaths: state => state.imgstore.img_paths,
   imgStatus: state => state.imgstore.img_status
  })
 },
 methods: {
  // 選擇圖片
  selectImgs () { # ①
   let fileList = this.$refs.file.files
   for (let i = 0; i < fileList.length; i++) {
    // 文件過(guò)濾
    if (fileList[i].name.match(/.jpg|.gif|.png|.bmp/i)) { 
     let item = {
      key: this.index++,
      name: fileList[i].name,
      size: fileList[i].size,
      file: fileList[i]
     }
     // 將圖片文件轉(zhuǎn)成BASE64格式
     let reader = new FileReader() # ②
     reader.onload = (e) => {
      this.$set(item, 'src', e.target.result)
     }
     reader.readAsDataURL(fileList[i])
     this.files.push(item)
     this.$store.commit('set_img_upload_cache', this.files) // 存儲(chǔ)文件緩存
     this.$store.commit('set_img_status', 'selected') // 更新文件上傳狀態(tài)
    }
   }
  },
  // 上傳圖片
  submit () {
   let formData = new FormData() # ③
   this.imgStore.forEach((item, index) => {
    item.name = 'imgFiles[' + index + ']' # ④
    formData.append(item.name, item.file)
   })
   formData.forEach((v, k) => console.log(k, ' => ', v))
   // 新建請(qǐng)求
   const xhr = new XMLHttpRequest() # ⑤
   xhr.open('POST', this.url, true)
   xhr.send(formData)
   xhr.onload = () => {
    if (xhr.status === 200 || xhr.status === 304) {
     let datas = JSON.parse(xhr.responseText)
     console.log('response: ', datas)
     // 存儲(chǔ)返回的地址
     let imgUrlPaths = new Set()  # ⑥
     datas.forEach(e => { // error === 0為成功狀態(tài)
      e.error === 0 && imgUrlPaths.add(e.url)
     })
     this.$store.commit('set_img_paths', imgUrlPaths) // 存儲(chǔ)返回的地址
     this.files = [] // 清空文件緩存
     this.index = 0 // 初始化序列號(hào)
     this.$store.commit('set_img_status', 'finished') // 更新文件上傳狀態(tài)
    } else {
     alert(`${xhr.status} 請(qǐng)求錯(cuò)誤!`)
    }
   }
  },
  // 移除圖片
  remove (index) {
   this.files.splice(index, 1)
   this.$store.commit('set_img_upload_cache', this.files) // 更新存儲(chǔ)文件緩存
  },
  // 清空?qǐng)D片
  empty () {
   this.files.splice(0, this.files.length)
   this.$store.commit('set_img_upload_cache', this.files) // 更新存儲(chǔ)文件緩存
   this.$store.commit('set_img_paths', [])
  }
 },
 beforeCreate () {
  this.$store.commit('set_img_status', 'ready') // 更新文件上傳狀態(tài)
 },
 destroyed () {
  this.$store.commit('set_img_upload_cache', [])
  this.$store.commit('set_img_paths', [])
 },
 watch: {
  imgStatus () {
   if (this.imgStatus === 'uploading') {
    this.submit()  # ⑦
   }
  },
  imgStore () {
   if (this.imgStore.length <= 0) {
    this.$store.commit('set_img_status', 'ready') // 更新文件上傳狀態(tài)
   }
  }
 }
}
</script>

<style lang="less" scoped>
...
</style>

以上代碼中有一些注釋序號(hào),是此插件設(shè)計(jì)的主要思路,其他代碼都比較容易理解,分別說(shuō)下

① 選擇文件后執(zhí)行,img_status狀態(tài)變?yōu)閟elected。
② 將帶上傳的圖片文件轉(zhuǎn)化為Base64格式,用于縮略圖顯示。
③ 創(chuàng)建一個(gè)表單對(duì)象,用于存儲(chǔ)待上傳的文件。
④ 注意這里的name屬性值,暫時(shí)寫死,后面設(shè)計(jì)打算從組件中指定name屬性,如果是多文件的話,name屬性的數(shù)組序號(hào)從0開(kāi)始遞增。
⑤ 未依賴任何Ajax請(qǐng)求插件,使用原生的XMLHttpRequest對(duì)象創(chuàng)建請(qǐng)求。
⑥ 存儲(chǔ)上傳成功后服務(wù)器返回的上傳路徑。
⑦ 檢測(cè)上傳狀態(tài),當(dāng)在使用此插件時(shí)將img_status的狀態(tài)設(shè)置為uploading時(shí)執(zhí)行上傳操作。

使用

參考本項(xiàng)目的GItHubNPM。

注意

使用此插件時(shí),需要與后端約定返回的數(shù)據(jù)格式,如下:

復(fù)制代碼 代碼如下:

[{"error":0,"url":"\/uploads\/api\/201711\/25\/fde412bd83d3ec5d6a49769bd0c143cd.jpg"},{"error":0,"url":"\/uploads\/api\/201711\/25\/c6fd51f0388c63a0b6d350331c945fb1.jpg"}]

預(yù)覽如下:


返回的是一個(gè)上傳后的路徑數(shù)組,包括error和url字段,每個(gè)文件有自己的上傳狀態(tài),當(dāng)error為0的時(shí)候?yàn)樯蟼鞒晒?,并返回上傳后的路徑url

改進(jìn)

后續(xù)版本打算進(jìn)行如下改進(jìn)

  1. 把表單的name屬性名稱通過(guò)組件傳遞。
  2. 自定義上傳成功后服務(wù)器響應(yīng)的數(shù)據(jù)格式,比如自定義error的名稱和其值所表示的狀態(tài)。
  3. 支持其他類型文件的上傳,可以在組件中自行制定上傳的文件類型,及其預(yù)覽方式。

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

相關(guān)文章

  • Vue組件之高德地圖地址選擇功能的實(shí)例代碼

    Vue組件之高德地圖地址選擇功能的實(shí)例代碼

    這篇文章主要介紹了Vue組件之 高德地圖地址選擇功能的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-06-06
  • vue實(shí)現(xiàn)錨點(diǎn)定位功能

    vue實(shí)現(xiàn)錨點(diǎn)定位功能

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)錨點(diǎn)定位功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • 淺談Vue服務(wù)端渲染框架Nuxt的那些事

    淺談Vue服務(wù)端渲染框架Nuxt的那些事

    這篇文章主要介紹了淺談Vue服務(wù)端渲染框架Nuxt的那些事,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • Vue.js+HighCharts實(shí)現(xiàn)動(dòng)態(tài)請(qǐng)求展示時(shí)序數(shù)據(jù)

    Vue.js+HighCharts實(shí)現(xiàn)動(dòng)態(tài)請(qǐng)求展示時(shí)序數(shù)據(jù)

    這篇文章主要為大家詳細(xì)介紹了Vue.js+HighCharts實(shí)現(xiàn)動(dòng)態(tài)請(qǐng)求展示時(shí)序數(shù)據(jù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 自定義vue組件發(fā)布到npm的方法

    自定義vue組件發(fā)布到npm的方法

    本篇文章主要介紹了自定義vue組件發(fā)布到npm的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05
  • 在vue組件中使用axios的方法

    在vue組件中使用axios的方法

    下面小編就為大家分享一篇在vue組件中使用axios的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • vue路由跳轉(zhuǎn)時(shí)判斷用戶是否登錄功能的實(shí)現(xiàn)

    vue路由跳轉(zhuǎn)時(shí)判斷用戶是否登錄功能的實(shí)現(xiàn)

    下面小編就為大家?guī)?lái)一篇vue路由跳轉(zhuǎn)時(shí)判斷用戶是否登錄功能的實(shí)現(xiàn)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10
  • vue中如何引入jQuery和Bootstrap

    vue中如何引入jQuery和Bootstrap

    本篇文章主要介紹了vue中如何引入jQuery和Bootstrap,詳細(xì)的介紹了引入jQuery和Bootstrap的方法,有興趣的可以了解一下。
    2017-04-04
  • TypeScript踩坑之TS7053的問(wèn)題及解決

    TypeScript踩坑之TS7053的問(wèn)題及解決

    這篇文章主要介紹了TypeScript踩坑之TS7053的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • vue生命周期與鉤子函數(shù)簡(jiǎn)單示例

    vue生命周期與鉤子函數(shù)簡(jiǎn)單示例

    這篇文章主要介紹了vue生命周期與鉤子函數(shù),結(jié)合簡(jiǎn)單實(shí)例形式分析了vue.js生命周期及鉤子函數(shù)相關(guān)流程與實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-03-03

最新評(píng)論

苍山县| 枝江市| 资阳市| 浑源县| 广元市| 隆安县| 方城县| 霞浦县| 枣庄市| 社旗县| 饶河县| 长海县| 临江市| 太谷县| 通河县| 都兰县| 昭苏县| 白河县| 彝良县| 寿光市| 安吉县| 通州区| 邵东县| 额尔古纳市| 香格里拉县| 鹤庆县| 奉化市| 衡水市| 光山县| 九龙城区| 金昌市| 招远市| 喀什市| 揭东县| 离岛区| 绥江县| 鹿泉市| 渝中区| 荃湾区| 开原市| 天门市|