Vue3实现图片拖曳上传组件
2022.04

作者用Vue3实现图片拖曳上传组件功能,非常实用

<template>
	<div class="upload-wrapper">
		<div class="item-wrapper landscape"
      :id="item.id"
      v-for="item in data.photos" :key="item.id"
      draggable="true"
      @dragstart.stop="funcs.drag($event)"
      @dragend="funcs.dragend($event)"
      @dragover="funcs.dragover(item.id,$event)"
      @dragleave="funcs.dragleave(item.id)"
      @drop="funcs.drop(item.id,$event)"
      :style="'background-image: url('+item.path+')'"
    ><div class="item"  ></div>

    <div class="del" @click="funcs.deletePhoto(item.id)">X</div>
    </div>

	
	</div>
  <div class="upload-btn"><input type="file" accept="image/*"  @change="funcs.uploadPhoto($event)">上传</div>
</template>

<script>

import {reactive} from 'vue'
import {onMounted} from 'vue'
import img1 from '../assets/1.jpg';
import img2 from '../assets/2.jpg';
import img3 from '../assets/3.jpg';
import img4 from '../assets/4.jpg';
export default{
	name:"UploadImage",
	setup(){

		let data =reactive({
			msg:"hell",
			photos:[
				{id:1,title:"",path:img1,sort:0},
				{id:2,title:"",path:img2,sort:0},
				{id:3,title:"",path:img3,sort:0},
				{id:4,title:"",path:img4,sort:0},
        {id:5,title:"",path:img1,sort:0},
        {id:6,title:"",path:img2,sort:0},
        {id:7,title:"",path:img3,sort:0},
        {id:8,title:"",path:img4,sort:0},
			]
			
		})
		let funcs =reactive({		
			drag:function(e){
				e.target.classList.add("hover");
				e.dataTransfer.setData("text/plain",e.target.id)
				e.dataTransfer.dropEffect = "copy";//拖曳时鼠标图标
			},
			dragend:function(e){				
				e.target.classList.remove("hover")
			},
			dragover:function(id,e){
        document.getElementById(id).classList.add("hover")
				e.preventDefault();
			},
			dragleave:function(id){
        document.getElementById(id).classList.remove("hover")
			},
			drop:function(id,e){

				document.getElementById(id).classList.remove("hover")
				let dragId=e.dataTransfer.getData('text/plain');
        this.sort(id,dragId);

			},
      sort:function(targetId,sourceId) {
        let target,source;
        data.photos.forEach(function(item){
          if( item.id==targetId){
            target=item;

          }
          if( item.id==sourceId){
            source=item;
          }
        })
        //互换位置
        data.photos.forEach(function(item,index,arr){

          if( item.id==target.id){
            arr[index]=source;
          }
          if( item.id==source.id){
            arr[index]=target;
          }
          arr[index].sort=(index+1)*10;
        })

      },
      uploadPhoto:function (event) {
        let r = new FileReader();
        r.readAsDataURL(event.target.files[0])
        r.onload = function (e){

          data.photos.push({id:9,title:"",path:this.result,sort:data.photos.length*10})
          //上传至服务器代码...
        }
      },
      deletePhoto:function (id) {
        data.photos.forEach(function(item,index,arr){
          if( item.id===id){
            data.photos.splice(index,1)

          }
        })
      }
		})
					
		onMounted(()=>{			

		})
		return{
			data,funcs,
		}
			
	}
	
	
}	
</script>

<style>
	.upload-wrapper{display: flex;flex-wrap:wrap;padding: 0.5%;}
	.upload-wrapper .item-wrapper{width: 24%; background-color: bisque;margin: 0.5%; position: relative;background-repeat: no-repeat;background-position: 50% 50%;}
  .upload-wrapper .item-wrapper,.landscape{background-size: 100% auto;}
  .upload-wrapper .item-wrapper .del{position: absolute; right: 0; top: 0; width: 20px; height: 20px; background-color: black;color: #fff;line-height: 20px;cursor: pointer}
  .upload-wrapper .item-wrapper .item{padding: 100% 50% 0% 0%;}
	.upload-wrapper .hover{opacity: 0.3;}

  .upload-btn{overflow: hidden;background-color: #42b983;position: relative; height: 100px;}
  .upload-btn input{opacity: 0.01;width: 100%; height: 100%;position: absolute;}
</style>

vue