废话少说, 直接上图!
使用方式:
- 创建drag.js文件
-
// 拖拽类 class Drag { constructor() { this.wrapEl = null this.innerEl = null this.nowEl = null this.isNest = false // 是否嵌套拖拽 this.data = [] // 是否嵌套拖拽 this.nowIndex = 0 // 拖拽中 拖拽dom的位置 this.toIndex = 0 // 拖拽中 目标dom的位置 this.start = 0 // 对应交换数据的 起始位置 this.end = 0 // 对应交换数据的 结束位置 this.vmodel = false // 是否需要拖拽绑定数据 } init(params) { this.wrapEl = params.el this.isNest = params.isNest this.data = params.data this.vmodel = params.vmodel ? params.vmodel : false this.innerEl = Array.from(params.el.children) if(this.data.length !== this.wrapEl.children.length && this.vmodel){ this.wrapEl.innerHTML = `<b style="color:red">Error: 拖拽dom的个数 和 数据的长度不匹配!</b>` return } this.addEvent() } // 添加拖拽一系列事件 addEvent() { let that = this this.wrapEl.ondragstart = (e) => { this.ondragstart(that, e) } this.wrapEl.ondragenter = (e) => { this.ondragenter(that, e) } this.wrapEl.ondragover = this.ondragover this.wrapEl.ondragend = (e) => { this.ondragend(that, e) } this.innerEl.forEach(item => { item.setAttribute('draggable', true) }) } // 拖拽开始事件 ondragstart(that, e) { let res = false if(that.findEl(e.target)){ if(that.vis(that.findEl(e.target))){ res = true } }else{ res = false } if(!res) return let elList = Array.from(that.wrapEl.children) that.nowEl = that.findEl(e.target) that.start = elList.indexOf(that.findEl(e.target)) that.findEl(e.target).classList.add("move"); console.log('拖拽开始'); } // 判断是否是可拖拽元素,要不会报错 vis(el) { return el.getAttribute('draggable') ? true : false } // 一直找可拖拽的元素网上递归找 findEl(el){ let res = null let recursion = (el) => { if(el) { if(el.getAttribute('draggable')){ res = el }else{ if(el.parentElement){ recursion(el.parentElement) } } } } recursion(el) return res } // 拖拽进入 ondragenter(that, e) { if(!that.nowEl) return //允许占用 e.preventDefault(); if(e.target === that.nowEl || e.target === that.wrapEl) { return } let toEl = that.findEl(e.target) let elList = Array.from(that.wrapEl.children) that.nowIndex = elList.indexOf(that.nowEl) that.toIndex = elList.indexOf(toEl) if(this.vmodel){ // 交换数据位置 let center = that.data[that.nowIndex] that.data[that.nowIndex] = that.data[that.toIndex] that.data[that.toIndex] = center } if(that.nowIndex < that.toIndex){ that.wrapEl.insertBefore(that.nowEl, toEl.nextElementSibling); }else{ that.wrapEl.insertBefore(that.nowEl, toEl); } } // 拖拽悬浮事件 ondragover(e) { e.preventDefault(); } // 拖拽中事件 ondrag(that, e) { if(e.target === that.nowEl) return console.log('拖拽中', e); } // 拖拽结束事件 ondragend(that, e) { if(!that.nowEl) return let elList = Array.from(that.wrapEl.children) that.end = elList.indexOf(that.nowEl) that.nowEl.classList.remove("move"); console.log('拖拽结束'); } } export default new Drag()
-
随便一个vue文件引入drag.js文件
-
<template> <h2>拖拽类</h2> <div ref="wrapDiv" class="wrapDiv"> <el-select v-for="item in data" :key="item.id" style="width:100%" v-model="item.value" placeholder="Select"> <el-option v-for="item in data" :key="item.id" :label="item.label" :value="item.id" /> </el-select> </div> <!-- 数据的响应式展示 --> <p v-for="item in data" :key="item">{{ item.id }}</p> </template> <script setup> import Drag from './drag' // 引入自己封装的Drag类 import { shallowRef, onMounted, reactive } from 'vue' let wrapDiv = shallowRef() // 获取dom,这里我不希望监听他的响应式,所以没用ref let data = reactive([ { id: 1, label: '苹果', value: '' }, { id: 2, label: '香蕉', value: '' }, { id: 3, label: '榴莲', value: '' }, { id: 4, label: '茄子', value: '' }, { id: 5, label: '菠萝', value: '' }, { id: 6, label: '草莓', value: '' }, { id: 7, label: '石榴', value: '' }, { id: 8, label: '奥里给', value: '' }, { id: 9, label: '葡萄', value: '' }, { id: 10, label: '猕猴桃', value: '' } ]) onMounted(() => { let params = { el: wrapDiv.value, // 容器,只能放一个根节点 vmodel: true, // 是否处理数据的响应 data: data // 数据 } Drag.init(params) // 调用拖拽类的方法 }) </script> <style scoped lang="scss"> .wrapDiv { border: 1px solid #dfdbdb; padding: 10px; } .el-select { margin-bottom: 20px; } .move { background: rgba(48,137,220,.1); color: #3089dc; box-sizing: border-box; border: 1px dashed #3089dc; border-top: 3px solid #3089dc; } </style>
完了就.....ojbk了....如此...如此简单.....
最后最后!!!
还不快打开你的 vscode ???,快上车!!!!