vue 拖拽
1、左右容器拖拽
2、容器内位置拖拽切换
3、判断性拖拽(若不适配,鼠标显示禁止拖拽图标)
4、点击大标题,变输入框修改,最后提交表单
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<template> <div> <div class="left_list"> <div class="_flex"> <transition-group tag="div"> <div class="item list_wrap" :class="'item' + index" v-for="(item, index) in dataList" :key="index" v-if="item.key!='box'" @drop='onDrop($event, item.key)' @dragover.prevent="dragOver($event, item,index)" @dragenter.prevent > <h2 v-on:dblclick="editTitle(index,true)" v-show="!item.showTitleEdit">{{ item.title }}</h2> <Input v-model="item.title" :autofocus="true" :ref="'editInput'+index" v-show="item.showTitleEdit" @on-blur="editTitle(index,false)"/> <p v-if="item.children&&item.children.length>0" v-for="(row,_index) in item.children" :key="_index" draggable="true" @dragstart="handleDragStart($event, item,index,_index)" @dragover.prevent="handleDragOver($event, item,index,_index)" @dragenter="handleDragEnter($event, item,index,_index)" @dragend="handleDragEnd($event, item,index,_index)"> {{ row.lable }} <Icon @click="deleteItem(index,_index)" type="md-close-circle"/> </p> </div> </transition-group> </div> <div class="_flex"> <transition-group tag="div"> <div class="item list_wrap" :class="'item' + index" v-for="(item, index) in dataList" :key="index" v-if="item.key=='box'" @drop='onDrop($event, item.key)' @dragover.prevent="dragOver($event, item,index)" @dragenter.prevent > <h2 v-on:dblclick="editTitle(index,true)" v-show="!item.showTitleEdit">{{ item.title }}</h2> <Input v-model="item.title" :autofocus="true" :ref="'editInput'+index" v-show="item.showTitleEdit" @on-blur="editTitle(index,false)"/> <p v-if="item.children&&item.children.length>0" v-for="(row,_index) in item.children" :key="_index" draggable="true" @dragstart="handleDragStart($event, item,index,_index)" @dragenter="handleDragEnter($event, item,index,_index)" @dragend="handleDragEnd($event, item,index,_index)"> {{ row.lable }} <Icon @click="deleteItem(index,_index)" type="md-close-circle"/> </p> </div> </transition-group> </div> </div> <div class="right_list"> <h1>检测限</h1> <div class="_list" v-for="(item,index) in rightList" :key="index"> <h2>{{ item.title }}</h2> <p v-if="item.children&&item.children.length>0" v-for="(row,_index) in item.children" :key="_index" draggable @dragstart='startDrag($event, item,index,_index)' @dragend="dragEnd($event, item,index,_index)">{{ row.lable }}</p> </div> </div> <Button @click="getD">按钮</Button> </div> </template> <script> export default { name: 'test2', data () { return { dataList: [ { title: '电源状态', key: 'power', showTitleEdit: false, children: [{lable: '电压(V)'}, {lable: '总电量'}, {lable: '电流(A)'}, {lable: '电压故障次数'}, {lable: '漏电流(mA)'}, {lable: '电流故障次数'}] }, { title: '环境', key: 'surroundings', showTitleEdit: false, children: [{lable: '温度1'}, {lable: '温度2'}, {lable: '湿度'}, {lable: '雷击次数'}] }, { title: 'IO输出', key: 'IOOutput', showTitleEdit: false, children: [{lable: '主继电器'}, {lable: '报警'}, {lable: 'LED'}, {lable: '风扇'}, {lable: '频闪灯'}] }, { title: '箱体布防状态', key: 'box', showTitleEdit: false, children: [{lable: '空开检测'}, {lable: '压敏监测'}, {lable: '门磁监测'}, {lable: '倾斜监测'}, {lable: '水浸监测'}, {lable: '雷击监测'}] } ], rightList: [ { title: 'IO输入', key: 'surroundings', children: [{lable: '电压11111'}, {lable: '总电量1111'}, {lable: '电流111(A)'}, {lable: '电压故障次数1111'}, {lable: '漏电流111(mA)'}, {lable: '电流故障次数111'}] }, { title: '模拟量', key: 'box', children: [{lable: '温度133333'}, {lable: '温度233333'}, {lable: '湿度33333'}, {lable: '雷击次数33333'}] }, { title: '电压值', key: 'power', children: [{lable: '主继电器2222'}, {lable: '报警2222'}, {lable: 'LED222'}, {lable: '风扇2222'}, {lable: '频闪灯222'}] } ], ending: null, dragging: null, newDrag: true, parentDragging: null } }, methods: { // 父拖动 startDrag (event, item, index, _index) { event.dataTransfer.dropEffect = 'move' event.dataTransfer.effectAllowed = 'move' this.newDrag = true this.parentDragging = Object.assign({}, item, {itemIndex: index, rowIndex: _index}) this.dragging = null this.ending = null }, dragOver(event, item, index) { // event.dataTransfer.dropEffect = 'move' if (this.newDrag) { //判断父类移入 event.dataTransfer.dropEffect = this.parentDragging.key == item.key ? 'move' : 'none' } }, dragEnd (event, item, index, _index) { this.newDrag = true }, onDrop (event, list) { if (list == this.parentDragging.key) { for (let item of this.dataList) { if (item.key == this.parentDragging.key) { item.children.push(this.rightList[this.parentDragging.itemIndex].children[this.parentDragging.itemIndex]) break } } } else { if (this.newDrag) { // 不是左边拖动 this.$Message.error('当前key不是同一个') } } }, // 子拖动 handleDragStart (e, item, index, _index) { this.newDrag = false this.parentDragging = null this.dragging = Object.assign({}, item, {index: index, _index: _index}) }, handleDragEnd (e, item) { if (this.ending.key != this.dragging.key) { return } let sourceIndex = this.dragging._index let targetIndex = this.ending._index let parentInex = this.dragging.index this.dataList[parentInex].children[sourceIndex] = this.dataList[parentInex].children.splice(targetIndex, 1, this.dataList[parentInex].children[sourceIndex])[0] }, handleDragOver (e, item, index, _index) { // e.dataTransfer.dropEffect = 'move' //判断子类移入 if (this.dragging) { if (this.ending.key != this.dragging.key) { e.dataTransfer.dropEffect = 'none' } else { e.dataTransfer.dropEffect = 'move' } } }, handleDragEnter (e, item, index, _index) { // 为需要移动的元素设置dragstart事件 e.dataTransfer.effectAllowed = 'move' this.ending = Object.assign({}, item, {index: index, _index: _index}) }, editTitle (index, bool) { this.dataList[index].showTitleEdit = bool this.$nextTick(() => { this.$refs['editInput' + index][0].focus() }) }, deleteItem (index, rowIndex) { this.dataList[index].children.splice(rowIndex, 1) }, getD () { console.log(this.dataList) } } } </script> <style scoped lang="less"> .right_list, .left_list { width: 49%; padding: 10px; display: inline-block; vertical-align: top; h2 { font-size: 1.5em; margin: 20px 20px 10px; } p { padding: 10px; display: inline-block; width: 48%; text-align: center; cursor: pointer; } } .left_list { background: #bcf5de; ._flex { margin: 10px; display: inline-block; width: 45%; vertical-align: top; } .list_wrap { margin-bottom: 10px; border: 1px solid red; } } .right_list { background: #fdbfab; } </style>