关于vue实现复制粘贴上传图片

本插件用到elementUi中的el-upload
主要能实现点击上传,拖拽上传,截图复制粘贴(鼠标右键操作与Ctrl+C Ctrl+V)上传,网页图片复制粘贴上传,本地图片复制粘贴上传暂时无解
话不多说上代码

<template>
  <div class="uploadImage">
    <el-upload
      :file-list="fileList"
      accept="image/*"
      action=""
      ref="uploadBtn"
      drag
      multiple
      list-type="picture-card"
      :limit="maxNum"
      :on-exceed="exceedTips"
      :on-remove="handleRemoveFile"
      :before-upload="handleUploadFile"
      :http-request="uploadFile"
      :on-preview="handlePicturePreview"
    >
      <i class="el-icon-plus"
      ref="uploadImage"
      @paste="handlePaste" 
      contenteditable="" 
      @keydown="handleFocus"></i>
      <div class="el-upload__text">{{uploadText}}</div>
      <div slot="file" slot-scope="{file}">
        <img
          class="el-upload-list__item-thumbnail"
          :src="file.originalUrl" alt="">
        <span class="el-upload-list__item-actions">
          <span
            class="el-upload-list__item-preview"
            @click="handlePicturePreview(file)">
            <i class="el-icon-zoom-in"></i>
          </span>
          <span
            class="el-upload-list__item-delete"
            @click="handleRemoveFile(file)">
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </div>
    </el-upload>
    <el-dialog 
      :visible.sync="dialogVisible" 
      :before-close="onCancel"
      append-to-body>
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
  </div>
</template>

<script>
import {uploadImageUsingFile} from '@/api/tools/upload'
export default {
  name: '',
  props: {
    fileList: {
      type: Array,
      default: () => []
    },
    uploadText: {
      type: String,
      default: () => ""
    },
    maxNum:{
      type: Number,
      default: () => 5
    }
  },
  components: {},
  data () {
    return {
      dialogVisible:false,
      dialogImageUrl:''
    }
  },
  computed: {},
  watch: {
    fileList(newVal,oldVal){
      this.$emit('getImage',newVal)
      if(newVal.length>=5){
        document.querySelector('.el-upload').style.display = 'none'
      }else{
        document.querySelector('.el-upload').style.display = 'inline-block'
      }
    }
  },
  created () {

  },
  mounted () {
  },
  beforeDestroy () {

  },
  methods: {
    handleFocus(){
      this.$refs.uploadImage.blur()
    },
    exceedTips: function () {
      this.$message.error(`最多只能上传${this.maxNum}张图片`)
    },
    handleRemoveFile(file) {
      let num = this.fileList.findIndex(i=>i.originalUrl==file.originalUrl)
      this.fileList.splice(num,1)
    },
    handleUploadFile(file) {
      let isImage = file.type.includes('image')
      let imgCount = this.fileList.length
      if(!isImage){
        this.$message.error('请上传图片格式的文件');
      }
      if(imgCount > this.maxNum){
        this.$message.error(`最多只能上传${this.maxNum}张图片`);
      }
      return isImage && imgCount
    },
    uploadFile(file) {
      //上传文件接口
      uploadImageUsingFile({imageFile: file.file, type: 3})
        .then(value => {
          //设置上传的路径
          if (value.code === '0') {
            this.fileList.push(value.data)
          }else{
            this.$message.error('图片上传失败')
          }
        })
        .catch(err => {
          this.$message.error('图片上传失败')
          console.log(err)
        })
    },
    handlePicturePreview(file){
      this.dialogImageUrl = file.originalUrl;
      this.dialogVisible = true;
    },
    onCancel(){
      this.dialogVisible = false
      this.dialogImageUrl = ''
    },
    handlePaste(event) {
      const items = (event.clipboardData || window.clipboardData).items;
      //去除粘贴到div事件
      event.preventDefault();
      event.returnValue=false;
      let file = null;
      if (!items || items.length === 0) {
        this.$message.error("当前不支持本地图片上传");
        return;
      }
      // 搜索剪切板items
      for (let i = 0; i < items.length; i++) {
        if (items[i].type.includes('image')) {
          file = items[i].getAsFile();
          break;
        }
      }
      if (!file) {
        this.$message.error("粘贴内容非图片");
        return;
      }
      this.uploadFile({file:file})
    }
  }
}
</script>

<style lang="scss" scoped>
.uploadImage{
    width: 100%;
    user-select: none;
    >>> .el-form-item__content{
      width: 97%;
      line-height: unset;
    }
    >>> .el-upload-list__item{
      width: 100px;
      height: 100px;
      margin: 0 8px 0 0;
      &.is-ready{
        display: none!important;
      }
      &.is-success{
        >:first-child{
          width: 100%;
          height: 100%;
        }
      }
    }
    >>> .el-upload--picture-card{
      width: 100px;
      height: 100px;
      line-height: unset;
      border: none;
      .el-upload-dragger{
        width: 100px;
        height: 100px;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        .el-icon-plus{
          position: absolute;
          width: 100%;
          height: 100%;
          top:20px;
          outline: none;
          caret-color: transparent;
        }
        .el-upload__text{
          font-size: 12px;
          font-weight: 700;
          margin-top: 28px;
          color: #8c939d;
        }
      }
    }
  }
</style>

网上基本都是键盘操作的复制粘贴功能上传,此处添加鼠标右键粘贴功能

i标签主要是负责复制粘贴功能 默认的标签是不带编辑功能的 所以使用contenteditable来添加编辑功能,鼠标点击元素右键会出现粘贴复制属性。但是在粘贴时会导致元素可编辑并且粘贴来的内容会添加到元素中展示!!!所以要处理粘贴的默认功能,在handlePaste方法中

event.preventDefault();
event.returnValue=false;

这样就不会把内容粘贴到元素中,但是点击也是会出现光标闪动,直接键盘输入也是会输入内容,还是要继续优化,给i标签绑定键盘事件@keydown="handleFocus"移除焦点,注意此处不可绑定@focus事件去除光标,这样会导致我们复制的内容找不到可复制的光标目标而粘贴功能失效,左键粘贴不可点击~~
虽然禁止了粘贴内容到元素中,但是光标还是能看到,我的笨方法是给i一个样式caret-color: transparent;这个样式是使光标透明~~~

基本的复制粘贴上传大同小异 本文主要是介绍我遇到的一些小难点

来吧展示~~~


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。