el-transfer 穿梭框右侧实现拖拽排序功能

通过 sortablejs 工具库,自定义指令来实现拖拽。

npm i sortablejs

directives/draggableTransfer.ts

import Sortable from 'sortablejs'
export function draggableTransfer(app: any) {
  app.directive('draggable-transfer', (el, binding) => {
    const { value } = binding
    const transferDoms = el.querySelectorAll('.el-transfer-panel__list')
    transferDoms &&
      transferDoms.length > 1 &&
      Sortable.create(transferDoms[1], {
        handle: '.btn-action', // 触发拖动事件的元素,
        draggable: '.el-transfer-panel__item', // 拖动触发时,可拖动的区域
        animation: 150,
        sort: true,
        disabled: false,
        onEnd(event: any) {
          // 这里可以根据需要更新数据源,例如调用binding.value回调函数传递拖动信息
          binding.value?.onDragenChange(event.oldIndex, event.newIndex)
        }
      })
  })
}

directives/index.ts

import type { App } from 'vue'
import { draggableTransfer } from './draggableTransfer'

/**
 * 导出指令:v-xxx
 * @methods draggableTransfer 穿梭框右侧拖拽排序,用法: v-draggable-transfer
 */
export const setupAuth = (app: App<Element>) => {
  draggableTransfer(app)
}

/**
 * 导出指令:v-mountedFocus
 */
export const setupMountedFocus = (app: App<Element>) => {
  app.directive('mountedFocus', {
    mounted(el) {
      el.focus()
    }
  })
}

<template>
  <el-transfer
    v-draggable-transfer="{ onDragenChange }"
    v-model="leftTranList"
    :titles="['待选列表', '分类包含产品']"
    filterable
    :filter-method="filterMethod"
    filter-placeholder="搜索关键词"
    :data="tranData"
  >
    <template #default="{ option }">
      <div class="flex items-center justify-between">
        <div>{{ option.label }}</div>
        <img
          v-if="leftTranList?.some((e) => e === option.key)"
          src="@/assets/svgs/drag.svg"
          class="w-[20px] h-[20px] btn-action"
          alt=""
          srcset=""
        />
      </div>
    </template>
  </el-transfer>
</template>
<script setup lang="ts">
const tranData = ref<any>([
  {
    label: 'California',
    key: 0
  },
  {
    label: 'New York',
    key: 1
  },
  {
    label: 'Los Angeles',
    key: 2
  },
  {
    label: 'Chicago',
    key: 3
  },
  {
    label: 'Houston',
    key: 4
  },
  {
    label: 'Phoenix',
    key: 5
  },
  {
    label: 'San Antonio',
    key: 6
  },
  {
    label: 'Dallas',
    key: 7
  },
  {
    label: 'Miami',
    key: 8
  },
  {
    label: 'Seattle',
    key: 9
  },
  {
    label: 'Boston',
    key: 10
  }
])

const filterMethod = (query, item) => {
  return item.label.toLowerCase().includes(query.toLowerCase())
}
// 左侧穿梭框数据列表
const leftTranList = ref([])
// 拖拽指令回调
const onDragenChange = (newIndex: number, oldIndex: number) => {
  //拿出要移动的元素,并从原来的位置移除
  const value = leftTranList.value.splice(newIndex, 1)[0]
  //将元素插入到新的位置中
  leftTranList.value.splice(oldIndex, 0, value)
}
</script>

在这里插入图片描述

### Vue2 中 Element UI `el-transfer` 穿梭组件的拖拽排序功能 #### 支持情况 Element UI 的标准 `el-transfer` 组件并不直接提供拖拽和排序的功能[^1]。然而,通过自定义扩展可以实现这些特性。 #### 实现方案 为了在 `el-transfer` 上启用拖拽排序功能,通常的做法是在原生基础上进行增强: ##### 方法一:利用第三方库 Sortable.js Sortable.js 是一个轻量级且易于使用的 JavaScript 库,专门用于创建可拖动和排序的列表。可以通过此库来增强 `el-transfer` 功能。 ```javascript import Sortable from 'sortablejs'; export default { mounted() { const transferDom = document.querySelector('.el-transfer-panel__list'); new Sortable(transferDom, { onEnd({ newIndex, oldIndex }) => { let targetItem; if (oldIndex !== undefined && newIndex !== undefined) { targetItem = this.targetOptions.splice(oldIndex, 1)[0]; this.targetOptions.splice(newIndex, 0, targetItem); } }, }); }, }; ``` ##### 方法二:重写事件处理函数 另一种方式是修改默认的选择变化监听器逻辑,在其中加入对拖拽的支持。这涉及到覆盖原有的 `leftCheckChange` 和 `rightCheckChange` 函数,并添加新的拖拽行为处理器。 ```javascript methods: { dragStart(event, item) { event.dataTransfer.setData('Text', JSON.stringify(item)); }, allowDrop(event) { event.preventDefault(); }, drop(event) { event.preventDefault(); const data = JSON.parse(event.dataTransfer.getData('Text')); // 更新数据源... }, leftCheckChange(value) { // 自定义左区选择改变后的操作 }, rightCheckChange(value) { // 自定义右区选择改变后的操作 } } ``` 上述两种方法都可以有效地为 `el-transfer` 添加拖拽及排序能力。具体采用哪种取决于项目需求和个人偏好。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vue1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值