Nuxt中实作图片上传组件

之前用JS写过文件上传,现在改用Vue的方式重新写一遍,发现清爽多了。附上成品及代码。

成品:

代码:

组件名:Attachment,props只有一个:最大允许上传的附件数量。

<template>
  <div class="attachment">
    <div class="p-2 rounded">
      <p class="mb-2">请选择图片上传: <span>(最多可上传{{ maxAttachmentsCount }}张图片)</span></p>
      <div class="preview d-block float-left">
        <div v-for="(file, index) in files" :key="`file_${index}`" class="pre-item mr-2">
          <div class="cover rounded">
            <img :src="file.src" />
          </div>
        </div>
      </div>
      <label :class="{ 'hidden-label': files.length >= parseInt(maxAttachmentsCount) }" class="d-flex align-items-center justify-content-center attachment-upload-area rounded bg-secondary border border-light mb-1">
        <i class="fas fa-camera fa-3x" style="color: white;"></i>
        <input type="file" class="d-none" @change="uploadAttachment">
      </label>
    </div>
  </div>
</template>

<script>
import $ from 'jquery'

export default {
  props: [ 'maxAttachmentsCount' ],
  data() {
    return {
      files: []
    }
  },
  methods: {
    uploadAttachment(event) {
      const file = $(event.target)[0]

      if (file.files[0].type.indexOf('image/') === -1) {
        alert('只能上传图片,请重新上传。')
        return false
      }

      if (file.files[0] !== undefined) {
        const reader = new FileReader()
        reader.readAsDataURL(file.files[0])
        reader.onloadend = (e) => {
          this.files.push({ src: e.target.result })
        }
        this.$el.querySelector('label').appendChild(event.target.cloneNode(true))
      }
    }
  }
}
</script>

<style scoped lang="scss">
  .attachment {
    margin-bottom: 1em;

    .pre-item {
      position: relative;
      display: inline-block;
      vertical-align: bottom;
    }

    .cover {
      width: 80px;
      height: 80px;
      overflow: hidden;

      img {
        max-height: 80px;
        width: auto;
        clip: rect(200px 300px 300px 200px);
      }
    }

    .attachment-upload-area {
      height: 80px;
      width: 80px;
    }
  }

  .hidden-label {
    visibility: hidden;
  }
}
</style>

感觉没什么需要特别解释的。

over。