Skip to content
yaml
meta:
  type: 组件
  category: 数据输入
title: 数据穿梭框 Transfer
description: 两栏布局的多选组件,将元素从一栏即时移到另一栏。

基本使用

数据穿梭框的基本用法。


代码事例
vue
<template>
  <fk-transfer :data="data" :default-value="value" />
</template>

<script>
export default {
  setup() {
    const data = Array.from({length: 8}).fill(undefined).map((_, index) => ({
      value: `option${index + 1}`,
      label: `Option ${index + 1}`
    }));
    const value = ['option1', 'option3', 'option5'];

    return {
      data,
      value
    }
  },
}
</script>

搜索

通过设置 show-search 来使用带搜索框的穿梭框,可以自定义搜索函数。


代码事例
vue
<template>
  <fk-transfer
    show-search
    :data="data"
    :default-value="value"
    :source-input-search-props="{
      placeholder:'source item search'
    }"
    :target-input-search-props="{
      placeholder:'target item search'
    }"
  />
</template>

<script>
export default {
  setup() {
    const data = Array.from({length: 8}).fill(undefined).map((_, index) => ({
      value: `option${index + 1}`,
      label: `Option ${index + 1}`
    }));
    const value = ['option1', 'option3', 'option5'];

    return {
      data,
      value
    }
  },
}
</script>

单向

通过设置 one-way ,使用单向模式的穿梭框。


代码事例
vue
<template>
  <fk-transfer :data="data" :default-value="value" one-way/>
</template>

<script>
export default {
  setup() {
    const data = Array.from({length: 8}).fill(undefined).map((_, index) => ({
      value: `option${index + 1}`,
      label: `Option ${index + 1}`
    }));
    const value = ['option1', 'option3', 'option5'];

    return {
      data,
      value
    }
  },
}
</script>

自定义选项渲染

通过 item 插槽自定义选项的渲染内容。


代码事例
vue

<template>
  <fk-transfer :data="data" :default-value="value">
    <template #item="{ label }">
      <icon-up />
      {{ label }}
    </template>
  </fk-transfer>
</template>

<script>
export default {
  setup() {
    const data = Array.from({length: 8}).fill(undefined).map((_, index) => {
      return {
        value: `option${index + 1}`,
        label: `Option ${index + 1}`,
        disabled: index === 1
      }
    });
    const value = ['option1', 'option3', 'option5'];

    return {
      data,
      value
    }
  },
}
</script>

简单模式

通过设置 simple 来开启简单模式,点击选项即可移动。


代码事例
vue
<template>
  <fk-transfer :data="data" :default-value="value" simple />
</template>

<script>
export default {
  setup() {
    const data = Array.from({length: 8}).fill(undefined).map((_, index) => ({
      value: `option${index + 1}`,
      label: `Option ${index + 1}`
    }));
    const value = ['option1', 'option3', 'option5'];

    return {
      data,
      value
    }
  },
}
</script>

树型穿梭框

通过穿梭框自定义接口可以实现树型穿梭框。


代码事例
vue

<template>
  <fk-transfer :data="transferData" :default-value="value">
    <template #source="{data,selectedKeys,onSelect}">
      <fk-tree
        :checkable="true"
        checked-strategy="child"
        :checked-keys="selectedKeys"
        :data="getTreeData(data)"
        @check="onSelect"
      />
    </template>
  </fk-transfer>
</template>

<script>
export default {
  setup() {
    const treeData = [
      {
        title: 'Trunk 0-0',
        key: '0-0',
        children: [
          {
            title: 'Leaf 0-0-1',
            key: '0-0-1',
          },
          {
            title: 'Branch 0-0-2',
            key: '0-0-2',
            children: [
              {
                title: 'Leaf 0-0-2-1',
                key: '0-0-2-1'
              },
              {
                title: 'Leaf 0-0-2-2',
                key: '0-0-2-2',
              }
            ]
          },
        ],
      },
      {
        title: 'Trunk 0-1',
        key: '0-1',
        children: [
          {
            title: 'Branch 0-1-1',
            key: '0-1-1',
            children: [
              {
                title: 'Leaf 0-1-1-1',
                key: '0-1-1-1',
              },
              {
                title: 'Leaf 0-1-1-2',
                key: '0-1-1-2',
              },
            ]
          },
          {
            title: 'Leaf 0-1-2',
            key: '0-1-2',
          },
        ],
      },
    ];

    const getTransferData = (treeData = [], transferDataSource = []) => {
      treeData.forEach((item) => {
        if (item.children) getTransferData(item.children, transferDataSource);
        else transferDataSource.push({label: item.title, value: item.key});
      });
      return transferDataSource;
    };

    const getTreeData = (data = []) => {
      const values = data.map(item => item.value)

      const travel = (_treeData = []) => {
        const treeDataSource = []
        _treeData.forEach((item) => {
          if (item.children || values.includes(item.key)) {
            treeDataSource.push({title: item.title, key: item.key, children: travel(item.children)})
          }
        });
        return treeDataSource
      }

      return travel(treeData)
    }

    const transferData = getTransferData(treeData);


    const value = ['0-0-2-1'];

    return {
      transferData,
      value,
      getTreeData
    }
  },
}
</script>

自定义标题栏

通过 source-title ,target-title 插槽自定义标题栏的渲染内容


代码事例
vue
<template>
  <fk-transfer :data="data" :default-value="value">
    <template
      #source-title="{
        countTotal,
        countSelected,
        checked,
        indeterminate,
        onSelectAllChange,
      }"
    >
      <div :style="styleHeader">
        Source Title {{ countSelected }}-{{ countTotal }}
        <fk-checkbox
          :model-value="checked"
          :indeterminate="indeterminate"
          @change="onSelectAllChange"
        />
      </div>
    </template>

    <template #target-title="{ countTotal, countSelected, onClear }">
      <div :style="styleHeader">
        Target Title {{ countSelected }}-{{ countTotal }}
        <IconDelete @click="onClear" />
      </div>
    </template>
  </fk-transfer>
</template>

<script>
import { IconDelete } from '@erp/common';

export default {
  components: { IconDelete },
  setup() {
    const data = Array.from({length: 8})
      .fill(undefined)
      .map((_, index) => ({
        value: `option${index + 1}`,
        label: `Option ${index + 1}`,
      }));
    const value = ['option1', 'option3', 'option5'];

    const styleHeader = {
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'space-between',
      paddingRight: '8px'
    };

    return {
      styleHeader,
      data,
      value,
    };
  },
};
</script>

API

<transfer> Props

参数名描述类型默认值版本
data穿梭框的数据TransferItem[][]
model-value (v-model)目标选择框中的值string[]-
default-value目标选择框中默认的值(非受控状态)string[][]
selected (v-model)选中的选项值string[]-
default-selected默认选中的选项值(非受控状态)string[][]
disabled是否禁用booleanfalse
simple是否开启简单模式(点击选项即移动)booleanfalse
one-way是否开启单向模式(仅可移动到目标选择框)booleanfalse
show-search是否显示搜索框booleanfalse
show-select-all是否展示全选勾选框booleantrue1.0.0
title源选择框和目标选择框的标题string[]['Source', 'Target']
source-input-search-props源选择框的搜索框配置object-1.0.0
target-input-search-props目标选择框的搜索框配置object-1.0.0
draggable拖拽排序boolean | DraggablePropsfalse

<transfer> Events

事件名描述参数
change目标选择框的值改变时触发value: string[]
select选中的值改变时触发selected: string[]
search用户搜索时触发value: string
type: 'target'|'source'

<transfer> Slots

插槽名描述参数版本
source源面板data: TransferItem[]
selectedKeys: string[]
onSelect: (value: string[]) => void
1.0.0
source-title源标题插槽countTotal: number
countSelected: number
searchValue: string
checked: boolean
indeterminate: boolean
onSelectAllChange: (checked:boolean) => void
onClear: () => void
1.0.0
to-target-icon移至目标图标插槽-1.0.0
to-source-icon移至源图标插槽-1.0.0
target目标面板data: TransferItem[]
selectedKeys: string[]
onSelect: (value: string[]) => void
1.0.0
target-title目标标题插槽countTotal: number
countSelected: number
searchValue: string
checked: boolean
indeterminate: boolean
onSelectAllChange: (checked:boolean) => void
onClear: () => void
1.0.0
item选项value: string
label: string

TransferItem

参数名描述类型默认值
value选项的值string-
label选项的标签string-
disabled是否禁用booleanfalse
sort排序number-

基于 MIT 许可发布