element-ui开发问题记录(二)

项目需求做一个和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传入初始数据

基本能实现需求穿梭框加排序的需求

猜你喜欢

转载自blog.csdn.net/qq_41114603/article/details/83383665
今日推荐