Vue3 + TS 可拖拽穿梭框

使用了sortablejs和element-plus
效果:
请添加图片描述

<!-- 可拖拽穿梭框 根据:https://www.jb51.net/article/204167.htm 修改而来 -->
<template>
  <div class="transfer" ref="transfer">
    <el-transfer v-model="value" :data="data" :titles="titles">
      <template #default="{ option }">
        <div class="pannel-content">
          <span :draggable="!option.disabled" @dragstart="drag($event, option)">{{ option.label
          }}</span>
        </div>
      </template>
    </el-transfer>
  </div>
</template>

<script lang="ts" setup>
import { TransferDataItem } from 'element-plus'
import Sortable from 'sortablejs'
import { ref, onMounted, computed } from 'vue'
const props = withDefaults(defineProps<{
  data: TransferDataItem[],
  titles?: [string, string]
}>(), {
  data: () => [{
    key: 1,
    label: `身份证取号`,
    disabled: false,
  }, {
    key: 2,
    label: `人脸取号`,
    disabled: false,
  }, {
    key: 3,
    label: `亮码取号`,
    disabled: false,
  }, {
    key: 4,
    label: `人证比对取号`,
    disabled: false,
  }],
  titles: () => ['待选列表', '已选列表']
})
const data = computed(() => props.data)
const titles = computed(() => props.titles)

const value = ref([] as any)
const draggingKey = ref(null as any)
const transfer = ref<HTMLDivElement | null>(null)
const drag = (ev: DragEvent, option: any) => {
  draggingKey.value = option.key
}
onMounted(() => {
  const leftPanel = transfer?.value?.getElementsByClassName("el-transfer-panel")[0].getElementsByClassName("el-transfer-panel__body")[0] as any;
  const rightPanel = transfer?.value?.getElementsByClassName("el-transfer-panel")[1].getElementsByClassName("el-transfer-panel__body")[0] as any;
  const leftEl = leftPanel?.getElementsByClassName("el-transfer-panel__list")[0]
  const rightEl = rightPanel?.getElementsByClassName("el-transfer-panel__list")[0]
  Sortable.create(rightEl, {
    onEnd: (evt: any) => {
      const { oldIndex, newIndex } = evt;
      const temp = value.value[oldIndex]
      if (!temp || temp === 'undefined') return;// 解决右边最后一项从右边拖左边,有undefined的问题
      value.value[oldIndex] = value.value[newIndex]
      value.value[newIndex] = temp
    }
  })
  Sortable.create(leftEl, {
    onEnd: (evt: any) => {
      const { oldIndex, newIndex } = evt;
      if (oldIndex === newIndex) return;
      const temp = data.value[oldIndex]
      if (!temp || (temp as any) === 'undefined') return;// 解决右边最后一项从右边拖左边,有undefined的问题
      data.value[oldIndex] = data.value[newIndex]
      data.value[newIndex] = temp
    }
  })
  leftPanel.ondragover = (ev: any) => {
    ev.preventDefault()
  }
  leftPanel.ondrop = (ev: any) => {
    ev.preventDefault();
    const index = value.value.indexOf(draggingKey.value)
    if (index !== -1) {
      value.value.splice(index, 1)
    }
  }
  rightPanel.ondragover = (ev: any) => {
    ev.preventDefault()
  }
  rightPanel.ondrop = (ev: any) => {
    ev.preventDefault();
    if (value.value.indexOf(draggingKey.value) === -1) {
      value.value.push(draggingKey.value)
    }
  }
})
</script>
<style scoped lang="scss">
:deep(.el-transfer__button) {
  width: 30px;
}
</style>


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值