vue附件拖拽排序解决方案

1、使用第三方库如:vuedraggable

(1)安装vuedraggable

npm install vuedraggable

(2)在Vue组件中使用vuedraggable

<template>
	<div>
		<draggable 
            v-model="urlPic" 
            @start="isDragging=true" 
            @end="isDragging=false" 
             v-bind="{animation:150,ghostClass:'sortable-ghost',chosenClass:'chosenClass',scroll:true,scrollSensitivity:200}">
            	<transition-group>
	            	<div v-for="(item, index) in urlPic" :key="index">
		                <div @click="deletPic(index)">
		                    <i class="el-icon-delete"></i>
		                </div>
		                <el-image :src="item.url" :preview-src-list="urlPic">
		                </el-image>
	            	</div>
            	</transition-group>
		</draggable>
	</div>
</template>
 
<script>
import draggable from 'vuedraggable';
 
export default {
  components: {
    draggable
  },
  data() {
    return {
      urlPic: [
        { id: 1, name: 'Item 1', url: '1.png' },
        { id: 2, name: 'Item 2', url: '2.png' },
        { id: 3, name: 'Item 3', url: '3.png' },
      ],
      isDragging: false
    };
  },
  methods: {
  }
};
</script>

官方文档:https://github.com/SortableJS/Vue.Draggable
中文文档:https://www.itxst.com/vue-draggable/tutorial.html

2、使用原生draggable拖拽方法

draggable=“true”,设置可拖拽属性

拖放事件总共有7个,
源元素触发事件3个

事件说明
dragstart开始拖放
dragenter拖放过程
dragend结束拖放

目标元素触发事件4个

事件说明
ondragenter当被拖放的元素进入本元素时
ondragover当被拖放的元素正在本元素范围内移动时
ondragover当被拖放的元素离开本元素时
ondrop当源元素释放到本元素时
<template>
  <div class="root">
    <transition-group tag="div" class="containers">
      <div
        class="item"
        v-for="(files, i) in (fileList || data.image)"
        :key="files.key"
        draggable="true"
        @dragstart="handleDragStart($event, files)"
        @dragover.prevent="handleDragOver($event, files)"
        @dragenter="handleDragEnter($event, files)"
        @dragend="handleDragEnd($event, files)"
      >
        <div>
          <img :src="files.url" :alt="files.name" :title="files.name" width="100px" height="100px">
          <div class="img-files-name">{{files.name}}</div>
          <div class="buttons image-button">
            <el-button class="el-icon-search" plain @click="imageSearch(files)"></el-button>
            <el-button class="el-icon-delete" plain @click="imageDelete(files)"></el-button>
          </div>
        </div>
      </div>
    </transition-group>
  </div>
</template>

<script type="text/javascript">
export default {
  name: 'image-preview',
  data() {
    return {
      ending: null,
      dragging: null,
      fileList: null,
    };
  },
  props: {
    data: {
      type: Object,
    },
  },
  mounted() {
    const { image } = this.data;
    // 前端根据附件名称做下去重
    if (image && image.length) {
      const map = new Map(image.map(item => [item.files.name, item]));
      const uniqueArr = [...map.values()];
      this.$set(this, 'fileList', uniqueArr);
    }
  },
  computed: {
  },
  methods: {
    // 用户开始拖动元素时触发
    handleDragStart(e, item) {
      this.dragging = item;
    },
    // 用户完成元素拖动后触发
    handleDragEnd() {
      if (this.ending.key === this.dragging.key) {
        return;
      }
      const newItems = [...this.data.image];
      const src = newItems.indexOf(this.dragging);
      const dst = newItems.indexOf(this.ending);
      newItems.splice(src, 1, ...newItems.splice(dst, 1, newItems[src]));

      this.data.image = newItems;
      this.$nextTick(() => {
        this.dragging = null;
        this.ending = null;
      });
    },
    // 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
    handleDragOver(e) {
      // 首先把div变成可以放置的元素,即重写dragenter/dragover
      // 在dragenter中针对放置目标来设置
      e.dataTransfer.dropEffect = 'move';
    },
    // 当被鼠标拖动的对象进入其容器范围内时触发此事件
    handleDragEnter(e, item) {
      // 为需要移动的元素设置dragstart事件
      e.dataTransfer.effectAllowed = 'move';
      this.ending = item;
    },
  },
};
</script>

<style lang="scss" scoped>
.containers {
  display: flex;
  flex-wrap: wrap;
}
.item {
  width: 100px;
  height: 100px;
  margin: 10px;
  color: #fff;
  transition: all linear 0.3s;
  //float: left;
  .img-files-name{
    top: -17px;
    position: relative;
    font-size: 10px;
    color: #000;
    width: 100px;
    display: -webkit-box;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
  .buttons {
    display: none;
    .el-button {
      padding: 7px 10px;
    }
    .el-icon-search {
      //margin: 7px;
      background-color:rgba(255,255,255,0.5);
    }
    .el-icon-download {
      //margin: 7px;
      background-color:rgba(255,255,255,0.5);
    }
    .el-icon-delete {
      //margin: 7px;
      background-color:rgba(255,255,255,0.5);
    }
  }
  .image-button {
    margin-left: 4px;
    top: -35px;
    width: 100px;
    position: relative;
  }
  .file-button {
    margin-top: 30px;
    width: 100px;
    position: relative;
  }
}
.item:hover .buttons {
  display: block;
}
</style>
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值