功能描述:
1、左边【一级、二级、三级】字样是不能拖拽的,【item1、item2…】可以拖拽
2、左边items位置固定,只能向右拖拽,不能上下拖拽,如:item7从左边拖到右边,左边的item7消失,右边增加item7
3、右边items可以自由拖拽,但不能向左拖拽
4、右边items可以删除,如:点击item7的“×”,右边item7消失,左边item7出现
5、重置时,页面回复初始化状态
实现方法:
1、左右json格式如下:
[crayon-600df503dead0236470749/]2、dom原始使用flex布局,拖拽时使用vue.DRAGGABLE插件,
下载地址:https://github.com/SortableJS/Vue.Draggable#start-of-content
演示地址:https://sortablejs.github.io/Vue.Draggable/#/simple
3、一开始左边加载所有的items,右边加载展示的items,注意:左边要过滤掉(隐藏)右边有的items,参考filterComs(left,right)方法;
在渲染dom、移动、删除时,通过操作dom来实现展示与隐藏;
4、左边draggle插件,:group=”{ name: ‘draGObj’, pull: ‘clone’, put: false}”
{ name: ‘dragobj’取相同名字的可以来回拖拽;pull: ‘clone’从左向右克隆,后面用右边draggle插件的dragChangeR()方法让左侧数据隐藏了,left并不是真正的删除这条数据;put: false 禁止从右向左拖放数据 }
:move=”checkMove” 移动时绑定checkMove方法,判断是上下还是向右移动,上下时,不执行拖拽;向右时,执行
5、右边draggle插件的deleteItme(element,index)方法实现删除时,right数据-1,左侧显示该条数据
6、【重置】时,重新调用this.filterComs(this.left,this.right);即可
7、问题:从左往右移动时,右侧一直会出现items的name值,拖拽结束后,name值消失,
解决方法:左右分别绑定一个v-bind=”dragOptionsL”,v-bind=”dragOptionsR”
8、问题:当右侧没有任何的items时,需要给右侧v-for循环的父元素指定一个min-height,否则从左侧拖到右侧时,没有接收的地方,则拖放失效
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
<template> <div class="box"> <div class="dragset-msg">请将左侧内容拖到右侧进行配置</div> <!-- 1 左边指标 --> <draggable tag="ul" class="lul" v-bind="dragOptionsL" :move="checkMove" :list="left" :group="{ name: 'dragobj', pull: 'clone', put: false}"> <li v-for="element in left" :key="element.name" :class="element.id?'dragindex':'dragtheme'" :ref="`li${element.indexid}`"> {{ element.name }} </li> </draggable> <!-- 2 右边展示区 --> <draggable tag="div" class="rconfig" group="dragobj" :list="right" v-bind="dragOptionsR" @change="dragChangeR" @start="drag = true" @end="drag = false"> <transition-group type="transition" :name="!drag ? 'flip-list' : null" tag="ul" class="rul"> <li class="showindex" v-for="(element,index) in right" :key="element.name" > {{ element.name }} <input type="button" class="btnindex" @click.stop="deleteItme(element,index)"> </li> </transition-group> </draggable> </div> </template> <script> import draggable from "vuedraggable"; import Vue from "vue"; export default { components: { draggable }, data() { return { blnShowDlg: false, dlgType: "add", // 窗口类型 titleName: "", // 窗口标题显示 settingData: {}, //获取左右配置数据 dataFormStore:{},//保存数据 left:[],//左边数据 right:[],//右边数据 drag:false, }; }, computed: { dragOptionsL() { return { disabled: false, ghostClass: "ghostL"//注意:在左侧上下移动时,使用这个类;移动到右侧时,使用ghostR类!!! }; }, dragOptionsR() { return { animation: 500, disabled: false, ghostClass: "ghostR"//注意:在右侧上下移动时,使用这个类; }; } }, methods: { /** 1、显示弹框 row不传为添加 传参为修改 */ showDlg(row) { this.titleName = "页面配置"; this.dlgType = "edit"; this.blnShowDlg = true; this.dataFormStore = this.$common.deepCopy(row);//存储原始数据 this.left=row.left; this.right=row.right; this.restoreForm(); }, // 2 左侧list移动,禁止在左侧上下移动 checkMove(evt){ let classObj=evt.to.className; if(evt.draggedContext.element.id===""){ return false; }else if(classObj.indexOf("lul")>-1){ return false; } }, // 2.1 拖拽事件,添加时隐藏左侧添加的数据 dragChangeR(evt) { if(evt.added){//这时候已经添加了 this.$refs[`li${evt.added.element.indexid}`][0].style.display='none'; } }, // 3 删除 deleteItme(element,index){ this.right.splice(index,1); this.$refs[`li${element.indexid}`][0].style.display='block'; }, // 4 取消 closeDialog() { this.blnShowDlg = false; }, // 5 关闭 hidDlg() { this.blnShowDlg = false; }, /** 6 修改-还原 */ restoreForm() { this.left=this.$common.deepCopy(this.dataFormStore.left); this.right=this.$common.deepCopy(this.dataFormStore.right); this.filterComs(this.left,this.right); }, /** 7 添加/保存 */ submitForm() { let newright=this.right; let rlens=this.right.length; if(rlens>0){ let idArr=[]; for(let i=0;i<rlens;i++){ idArr.push(newright[i].indexid); } this.$emit("doSaveRow",idArr); // 把id数组传递过去 }else{ this.$HiAlert.showFail(this.$HiAlert.getMsgText("至少选择一个菜单")); } }, // 8 过滤不显示的左侧item filterComs(left,right){ if(right.length > 0){ // 初始化,全置为blcok,后面根据right数据过滤显示 for(let i=0;i< left.length;i++){ this.$nextTick(() => { this.$refs[`li${left[i].indexid}`][0].style.display='block'; }); } for(let i=0;i< right.length;i++){ let filteritem=left.filter((element,index,self)=>{ return element.indexid==right[i].indexid; }); // 右侧有数据时,dom生成之后再来渲染,否则会报错:cannot read property '0' of undefined this.$nextTick(() => { this.$refs[`li${filteritem[0].indexid}`][0].style.display='none'; }); } } } } }; </script> <style lang="stylus" scoped> //应用样式文件 .ghostL{ opacity:0.5; width:230px; } .ghostR{ opacity:0; width:230px; } </style> |
评论抢沙发