求点赞关注!!!!!!!!!!!!! 

最近在写公司项目时需要在Ant Design Vue穿梭框右侧实现拖拽列表排序功能,而Ant Design Vue本身无此功能,所以自己写了一个,实现代码及原理如下:

//使用到VUE中的:
@dragstart 拖拽开始时在被拖拽元素上触发此事件
@drop.prevent 被拖拽的元素在目标元素上同时鼠标放开触发的事件,此事件作用在目标元素上
@dragover.prevent 拖拽元素在目标元素上移动的时候触发的事件,此事件作用在目标元素上

 1.Transfer 穿梭框HTML代码

<a-transfer :style="{width: '400px'}"  :data-source="mockData"
        :titles="['列表', '已选列表']" :disabled="disabled"
        :target-keys="formState.targetKeys" :selected-keys="transfer.selectedKeys"
        :render="item => item.title" @change="handleChange" @selectChange="handleSelectChange">
            <template #children="{direction,filteredItems,onItemSelect}">
              <div class="transfer">
              <div v-if="direction==='right'" class="transfer-right">
                <div draggable="true" v-for="(item,index) in filteredItems" :key="item.key"
                @mouseenter="isTarget(true,item)"
                @mouseleave="isTarget(false,item)"
                @dragstart="handleDragstart(index)"
                @drop.prevent="handleDrop()"
                @dragover.prevent="handleDragover(index)"
                @click="()=>checkChange(item.checked,item.key,onItemSelect)"
                 class="transfer-right-item"
                >
                <a-checkbox
                :checkedKeys="[...formState.targetKeys, ...transfer.selectedKeys]"
                 v-model:checked="item.checked"
                 ></a-checkbox>
                 <div class="transfer-right-item-content">
                  <span> &nbsp;{{item.title}}</span>
                  <MenuOutlined v-show="item.showMenu" />
                 </div>
                </div>
              </div>
              <div v-if="direction==='left'"  class="transfer-left">
                <div v-for="item in filteredItems" :key="item.key"  class="transfer-left-item"
                @click="()=>checkChange(item.checked,item.key,onItemSelect)">
                  <a-checkbox
                :checkedKeys="[...formState.targetKeys, ...transfer.selectedKeys]"
                 v-model:checked="item.checked"
                 ></a-checkbox>
                &nbsp; {{item.title}}
                </div>
              </div>
              </div>
            </template>
        </a-transfer>

2.Transfer 穿梭框JavaScript代码

setup()中的代码,下面的所用到的函数代码

    
    // 选项在两栏之间转移时的回调函数
    const handleChange = (nextTargetKeys, direction, moveKeys) => {
      moveKeys.forEach((item) => {
        drawerData.mockData.forEach((items, index) => {
          if (item === items.key)drawerData.mockData[index].checked = false;
        });
      });
      if (direction === 'right') {
        formState.targetKeys.push(...moveKeys);
      } else formState.targetKeys = nextTargetKeys;
    };
    // 选中项发生改变时的回调函数
    const handleSelectChange = (sourceSelectedKeys, targetSelectedKeys) => {
      // 判断右边列表是否全选  是的话右边多选框全为true
      if (targetSelectedKeys.length === formState.targetKeys.length) {
        targetSelectedKeys.forEach((item) => {
          drawerData.mockData.forEach((items, index) => {
            if (item === items.key)drawerData.mockData[index].checked = true;
          });
        });
      }
      // 判断左边列表是否全选 是的话左边多选框全为true
      if (sourceSelectedKeys.length === drawerData.mockData.length - formState.targetKeys.length) {
        sourceSelectedKeys.forEach((item) => {
          drawerData.mockData.forEach((items, index) => {
            if (item === items.key)drawerData.mockData[index].checked = true;
          });
        });
      }
      drawerData.transfer.selectedKeys = [...sourceSelectedKeys, ...targetSelectedKeys];
    };
    const handleDrop = () => {
      // 删除老的
      const changeItem = formState.targetKeys.splice(drawerData.oldItemIndex, 1)[0];
      // 在列表中目标位置增加新的
      formState.targetKeys.splice(drawerData.newItemIndex, 0, changeItem);
    };
    const handleDragstart = (index) => { drawerData.oldItemIndex = index; };
    const handleDragover = (index) => { drawerData.newItemIndex = index; };
    // 用于判断选中了哪些多选框
    const checkChange = (checked, key, onItemSelect) => {
      drawerData.mockData.forEach((items, index) => {
        if (key === items.key)drawerData.mockData[index].checked = !checked;
      });
      onItemSelect(key, !checked);
    };
    // 穿梭框列表图标显示与隐藏
    const isTarget = (falg, e) => {
      let key = false;
      formState.targetKeys.forEach((item) => { if (e.key === item)key = item; });
      if (key !== false) {
        drawerData.mockData.forEach((item, index) => {
          if (e.key === item.key)drawerData.mockData[index].showMenu = falg;
        });
      }
    };

 3.Transfer 穿梭框样式代码

我使用的是less,大家可以根据自己的需求进行更改

:deep(.ant-transfer-list-body){
  width: 100px;
  height: 200px;
}
:deep(.ant-transfer-list-body-customize-wrapper){
  padding: 0 12px 0 0px;
  height: 100%;
}
.transfer{
  width: 178px;
   height: 200px;
  overflow: hidden;
}
.transfer-left,.transfer-right{
   width:100%;
   height: 200px;
  overflow-y: auto;
  &-item{
    padding-left: 12px;
     width: 100%;
    height: 30px;
    display: flex;
    align-items: center;
    &-content{
      width: 100%;
      display: flex;
      padding: 10px;
      align-items: center;
      justify-content: space-between;
    }
  }
  &-item:hover{
    background: #ccc;
  }
}

Logo

前往低代码交流专区

更多推荐