Vue3 + Element Plus Transfer 穿梭框自定义分组的示例详解

 更新时间:2025年07月03日 10:30:33   作者:滿  
本文介绍Vue3结合ElementPlus实现Transfer穿梭框自定义分组的四种方法,每种方法结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧

1. 使用render-content自定义渲染

<template>
  <el-transfer
    v-model="selectedData"
    :data="groupedData"
    :render-content="renderFunc"
    :titles="['可选数据', '已选数据']"
  />
</template>
<script setup>
import { ref } from 'vue';
const selectedData = ref([]);
// 分组数据格式
const groupedData = ref([
  {
    key: 'group1',
    label: '第一组',
    disabled: false,
    children: [
      { key: '1', label: '选项1' },
      { key: '2', label: '选项2' }
    ]
  },
  {
    key: 'group2',
    label: '第二组',
    disabled: false,
    children: [
      { key: '3', label: '选项3' },
      { key: '4', label: '选项4' }
    ]
  }
]);
// 扁平化数据供Transfer使用
const flatData = computed(() => {
  return groupedData.value.flatMap(group => 
    group.children.map(item => ({
      key: item.key,
      label: item.label,
      disabled: item.disabled
    }))
  );
});
// 自定义渲染函数
const renderFunc = (h, option) => {
  // 这里可以自定义渲染逻辑
  return h('div', option.label);
};
</script>

2. 完全自定义左右面板

如果需要更复杂的分组效果,可以完全自定义左右面板:

<template>
  <div class="custom-transfer">
    <div class="transfer-panel">
      <div class="panel-header">可选数据</div>
      <div class="panel-body">
        <div v-for="group in leftGroups" :key="group.key" class="group">
          <div class="group-title">{{ group.label }}</div>
          <div class="group-items">
            <el-checkbox 
              v-for="item in group.children" 
              :key="item.key"
              v-model="item.checked"
              :label="item.label"
              @change="handleLeftChange(item)"
            />
          </div>
        </div>
      </div>
    </div>
    <div class="transfer-buttons">
      <el-button @click="moveToRight">→</el-button>
      <el-button @click="moveToLeft">←</el-button>
    </div>
    <div class="transfer-panel">
      <div class="panel-header">已选数据</div>
      <div class="panel-body">
        <div v-for="group in rightGroups" :key="group.key" class="group">
          <div class="group-title">{{ group.label }}</div>
          <div class="group-items">
            <el-checkbox 
              v-for="item in group.children" 
              :key="item.key"
              v-model="item.checked"
              :label="item.label"
              @change="handleRightChange(item)"
            />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref, computed } from 'vue';
// 原始分组数据
const rawData = ref([
  {
    key: 'group1',
    label: '第一组',
    children: [
      { key: '1', label: '选项1', checked: false },
      { key: '2', label: '选项2', checked: false }
    ]
  },
  {
    key: 'group2',
    label: '第二组',
    children: [
      { key: '3', label: '选项3', checked: false },
      { key: '4', label: '选项4', checked: false }
    ]
  }
]);
// 计算左侧分组数据
const leftGroups = computed(() => {
  return rawData.value.map(group => ({
    ...group,
    children: group.children.filter(item => !selectedData.value.includes(item.key))
  }));
});
// 计算右侧分组数据
const rightGroups = computed(() => {
  const selectedKeys = selectedData.value;
  return rawData.value
    .map(group => ({
      ...group,
      children: group.children.filter(item => selectedKeys.includes(item.key))
    }))
    .filter(group => group.children.length > 0);
});
// 移动选中项到右侧
const moveToRight = () => {
  rawData.value.forEach(group => {
    group.children.forEach(item => {
      if (item.checked && !selectedData.value.includes(item.key)) {
        selectedData.value.push(item.key);
        item.checked = false;
      }
    });
  });
};
// 移动选中项到左侧
const moveToLeft = () => {
  rawData.value.forEach(group => {
    group.children.forEach(item => {
      if (item.checked && selectedData.value.includes(item.key)) {
        const index = selectedData.value.indexOf(item.key);
        selectedData.value.splice(index, 1);
        item.checked = false;
      }
    });
  });
};
</script>
<style scoped>
.custom-transfer {
  display: flex;
  align-items: center;
}
.transfer-panel {
  width: 250px;
  border: 1px solid #ebeef5;
  border-radius: 4px;
}
.panel-header {
  padding: 10px;
  background: #f5f7fa;
  border-bottom: 1px solid #ebeef5;
}
.panel-body {
  padding: 10px;
  height: 300px;
  overflow: auto;
}
.group {
  margin-bottom: 15px;
}
.group-title {
  font-weight: bold;
  margin-bottom: 5px;
}
.transfer-buttons {
  margin: 0 10px;
}
</style>

3. 使用插槽自定义内容

Element Plus 的 Transfer 组件提供了插槽来自定义内容:

<el-transfer v-model="value" :data="data">
  <template #left-footer>
    <el-button size="small">操作</el-button>
  </template>
  <template #right-footer>
    <el-button size="small">操作</el-button>
  </template>
</el-transfer>

4. 结合 Tree 组件实现树形分组

如果需要树形分组,可以结合 Tree 组件来实现:

<template>
  <div class="tree-transfer">
    <div class="left-panel">
      <el-tree
        :data="treeData"
        show-checkbox
        node-key="id"
        ref="leftTree"
        @check-change="handleCheckChange"
      />
    </div>
    <div class="transfer-buttons">
      <el-button @click="moveToRight">→</el-button>
      <el-button @click="moveToLeft">←</el-button>
    </div>
    <div class="right-panel">
      <el-tree
        :data="selectedTreeData"
        show-checkbox
        node-key="id"
        ref="rightTree"
      />
    </div>
  </div>
</template>

到此这篇关于Vue3 + Element Plus Transfer 穿梭框自定义分组的文章就介绍到这了,更多相关Vue3 Element Plus Transfer 穿梭框内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue+el-table点击表头实现改变其当前样式

    vue+el-table点击表头实现改变其当前样式

    这篇文章主要介绍了vue+el-table点击表头实现改变其当前样式问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Vue引入Stylus知识点总结

    Vue引入Stylus知识点总结

    在本篇文章里小编给各位整理的是一篇关于Vue引入Stylus知识点总结内容,有需要的朋友们可以学习参考下。
    2020-01-01
  • 详解Vue的mixin策略

    详解Vue的mixin策略

    这篇文章主要介绍了Vue的mixin策略的相关资料,帮助大家更好的理解和学习vue框架,感兴趣的朋友可以了解下
    2020-11-11
  • Vue3使用sessionStorage保存会话数据的实现方式

    Vue3使用sessionStorage保存会话数据的实现方式

    在前端开发中,我们常常需要在用户会话期间保存一些数据,这些数据在页面刷新或导航时依然需要存在,sessionStorage 是一种非常方便的方式来实现这一点,在这篇文章中,我们将探讨如何在Vue3应用中使用sessionStorage来保存会话数据,需要的朋友可以参考下
    2025-01-01
  • vue实现滑动和滚动效果

    vue实现滑动和滚动效果

    这篇文章主要为大家详细介绍了vue实现滑动和滚动效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • vue路由传参及获取参数的方式总结

    vue路由传参及获取参数的方式总结

    这篇文章主要介绍了vue路由传参及获取参数的方式总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • vue-cli 3.x 修改dist路径的方法

    vue-cli 3.x 修改dist路径的方法

    今天小编就为大家分享一篇vue-cli 3.x 修改dist路径的方法,具有很好的参考价值。希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • vue element 多图片组合预览的实现

    vue element 多图片组合预览的实现

    本文主要介绍了vue element多图片预览实现的相关资料,最近的项目中有图片预览的场景,本文就来介绍一下如何使用,感兴趣的可以了解一下
    2023-08-08
  • Vue实现dom元素拖拽并限制移动范围的操作代码

    Vue实现dom元素拖拽并限制移动范围的操作代码

    这篇文章主要介绍了Vue实现dom元素拖拽并限制移动范围的操作代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-12-12
  • 详解vue中使用protobuf踩坑记

    详解vue中使用protobuf踩坑记

    这篇文章主要介绍了vue中使用protobuf踩坑记,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05

最新评论