element-ui開發問題記錄(二)
阿新 • • 發佈:2018-12-17
專案需求做一個和element中穿梭框一樣的效果,但是要求多家一個功能,就是右邊的資料要實現拖動排序的效果;沒辦法,不能用element現成的元件,只能自己封裝;程式碼
<template> <div class="customItems"> <div class="customList"> <p class="title"><el-checkbox v-model="leftAll" @change="checkAll($event,left,'left')">左邊列表</el-checkbox></p> <div class="checkboxList"> <el-checkbox class="checkbox" @change="check('left')" v-model="item.checked" v-for="item in left" :key="item.id">{{item.name}}</el-checkbox> </div> </div> <div class="center"> <el-button class="btn" size="mini" :disabled="!toRightFlag" @click="toRight" icon="el-icon-d-arrow-right"></el-button> <el-button class="btn" size="mini" :disabled="!toLeftFlag" @click="toLeft" icon="el-icon-d-arrow-left"></el-button> </div> <div class="checkedList"> <p class="title"><el-checkbox v-model="rightAll" @change="checkAll($event,right,'right')">已選擇</el-checkbox><el-button class="sort" type="text" v-show="right.length>1" @click="sort">{{sortFlag?'儲存':'排序'}}</el-button></p> <div class="checkboxList"> <el-checkbox class="checkbox" @change="check('right')" v-model="item.checked" v-for="item in right" v-show="!sortFlag" :key="item.id">{{item.name}}</el-checkbox> <p :class="{checkbox:true, dragBox:true,active:active===item.id}" :style="{top:top+'px'}" @mousedown="moveStart($event,item.id,index)" v-for="item,index in right" v-show="sortFlag">{{item.name}}</p> </div> </div> </div> </template> <script> export default { data(){ return { left:[], right:[], leftAll:false, rightAll:false, toLeftFlag:false, toRightFlag:false, sortFlag:false, active:"", x:0, y:0, l:0, top:0 } }, computed : {}, methods : { //資料初始化 dataInit(list){ for(let i=0,len=this.left.length; i<len; i++){ if(list.indexOf(this.left[i].id)!==-1){ this.right.push(JSON.parse(JSON.stringify(this.left[i]))); this.left.splice(i,1); i--; len--; } } }, //兩邊的全選事件 checkAll(val,arr,key){ arr.forEach(e=>{ e.checked=val; }); this[key]=JSON.parse(JSON.stringify(this[key])); this.check(key) }, //單選事件 check(key){ for(let i=0,len=this[key].length; i<len; i++){ if(this[key][i].checked){ key==="left"?this.toRightFlag=true:this.toLeftFlag=true; return; } } key==="left"?this.toRightFlag=false:this.toLeftFlag=false; }, //移動選中項到右邊 toRight(){ for(let i=0,len=this.left.length; i<len; i++){ if(this.left[i].checked){ this.left[i].checked=false; this.right.push(JSON.parse(JSON.stringify(this.left[i]))); this.left.splice(i,1); i--; len=this.left.length } } this.toRightFlag=this.leftAll=false; this.change(); }, //移動選中項到左邊 toLeft(){ for(let i=0,len=this.right.length; i<len; i++){ if(this.right[i].checked){ this.right[i].checked=false; this.left.push(JSON.parse(JSON.stringify(this.right[i]))); this.right.splice(i,1); i--; len=this.right.length } } this.toLeftFlag=this.rightAll=false; this.change(); }, //右邊資料發生變化時,處理資料格式,同時出發change事件;裡面的邏輯可以自己編輯 change(){ let res=[]; this.right.forEach(e=>{ res.push(e.id) }); this.$emit("change",res) }, //排序按鈕和儲存按鈕點選事件 sort(){ this.sortFlag=!this.sortFlag; if(!this.sortFlag){ this.change(); } }, //開始拖動 moveStart(e,id,index){ this.x=e.clientX; this.y=e.clientY; this.index=index; this.active=id; document.addEventListener("mousemove",this.moveing,false); document.addEventListener("mouseup",this.moveEnd,false); }, //拖動中 moveing(e){ this.l=e.clientX-this.x; this.top=e.clientY-this.y; if(this.top>0){//向下 if(this.index<this.right.length-1){ if(this.top>=15){ this.right[this.index+1]=this.right.splice(this.index,1,this.right[this.index+1])[0]; this.index+=1; this.y+=30; this.top-=30; } } }else {//向上 if(this.index>0){ if(this.top<=-15){ this.right[this.index-1]=this.right.splice(this.index,1,this.right[this.index-1])[0]; this.index-=1; this.y-=30; this.top +=30; } } } }, //拖動結束 moveEnd(e){ document.removeEventListener("mousemove",this.moveing);//移除滑鼠移動事件 document.removeEventListener("mouseup",this.moveEnd);//移除事件 this.l=this.top=0; this.active=""; this.index=0; } }, mounted(){ this.left=this.$attrs.data } } </script> <style scoped> .customItems{ display:flex; } .customList,.checkedList{ border: 1px solid #ebeef5; border-radius: 4px; overflow: hidden; background: #fff; display: inline-block; vertical-align: middle; width: 240px; max-height: 100%; box-sizing: border-box; position: relative; } .customList{ } .title{ height: 40px; line-height: 40px; background: #f5f7fa; margin: 0; padding-left: 15px; border-bottom: 1px solid #ebeef5; box-sizing: border-box; color: #000; } .checkboxList{ margin: 0; padding: 6px 0; list-style: none; height: 246px; overflow: auto; box-sizing: border-box; } .checkbox{ height: 30px; line-height: 30px; padding-left: 15px; display: block; margin:0; } .sort{ float:right; margin-right:30px; } .dragBox{ cursor:pointer; -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none; } .dragBox.active{ position:relative; background-color:rgba(0,0,0,.3); } .center{ width:80px; display:flex; flex-direction:column; justify-content:center; align-items:center; } .center .btn{ padding:0; margin:10px; width:30px; height:30px; } </style>
元件引用
<Transfer ref="transfer " :data="data" @change="change"></Transfer>
data是供選擇的陣列資料; change是右邊的資料發生變化是的回撥事件;方便修改表單中繫結的值,返回引數為右邊的資料 如果有初始資料,需要呼叫元件的dataInit方法進行資料初始化
this.$refs.transfer.dataInit(list)//list傳入初始資料
基本能實現需求穿梭框加排序的需求