IDuxFE / idux

🚀 A UI Component Library for Vue3.x
https://idux.site
MIT License
552 stars 141 forks source link

[comp:transfer] add transfer component #782

Closed sallerli1 closed 2 years ago

sallerli1 commented 2 years ago

What problem does this feature solve?

add basic transfer component

What does the proposed API look like?

Components Structure

Transfer____ TransferSourceList____ TransferListItem
             |                |____ TransferListHeader
             |                |____ TransferListBody
             |                |____ TransferListFooter
             |
             |____ TransferOperations

API

TransferBindings

穿梭框列表统一使用的参数集合,在插槽与依赖注入时使用,通常用于穿梭框列表自定义,参数根据源数据列表与目标数据列表而划分,详细见下方文档

export interface TransferBindings<T = unknown> {
  // 分割好的数据
  data: ComputedRef<T[]>
  // 过滤后的数据
  filteredData: ComputedRef<T[]>
  // 分页处理过后的数据
  paginatedData: ComputedRef<T[]>
  // 源数据
  dataSource: ComputedRef<T[]>
  // 数据key与数据项对应Map
  dataKeyMap: ComputedRef<Map<VKey, T>>
  // 过滤后的源数据
  filteredDataSource: ComputedRef<T[]>
  // 分页后的源数据
  paginatedDataSource: ComputedRef<T[]>
  // 已选数据
  selectedData: ComputedRef<T[]>
  // 已选数据key集合
  selectedKeys: ComputedRef<Set<VKey>>
  // 已勾选数据
  checkedKeys: ComputedRef<Set<VKey>>
  // 禁用数据key集合
  disabledKeys: ComputedRef<Set<VKey>>
  // 全部勾选状态
  checkAllStatus: ComputedRef<boolean>

  // 是否展示左右箭头操作按钮
  showOperations: ComputedRef<boolean>
  // 是否展示全部勾选框
  showCheckAll: ComputedRef<boolean>
  // 是否可搜索
  searchable: ComputedRef<boolean>
  // 分页配置
  pagination: ComputedRef<PaginationProps | null>

  // 勾选状态改变触发函数
  handleCheckChange: (keys: Set<VKey> | VKey[]) => void
  // 增加已选数据触发函数
  triggerAppend: (data?: T[]) => void
  // 移除已选数据触发函数
  triggerRemove: (keys?: VKey[]) => void
  // 清除已选数据触发函数
  triggerClear: () => void
  // 数据key获取函数
  getRowKey: GetRowKey
  // 全部勾选触发函数
  checkAll: (checked?: boolean) => void

  // 搜索输入
  searchValue: ComputedRef<string | undefined>
  // 搜索输入触发函数
  handleSearchChange: (value: string | undefined) => void
}

IxTransfer

TransferProps

名称 说明 类型 默认值 全局配置 备注
dataSource 源数据数组 object[] [] - -
v-model:selectedData 已选数据数组 - - - -
disabled 是否禁用穿梭框 boolean false - -
itemDisabled 数据项禁用判断逻辑 (item: unknown) => boolean item => item.disabled - -
rowKey 数据项 key 的取值 string \| (item: unknown) => string \| number 'key' - -
virtual 是否开启虚拟滚动 boolean false - 需要设置 scroll.y
onSourceScroll 源数据列表滚动事件 (evt: Event) => void - - 仅使用默认列表并开启 virtual 下可用
onSourceScrolledChange 源数据列表滚动的位置发生变化 (startIndex: number, endIndex: number, visibleNodes: unknown[]) => void - - 仅使用默认列表并开启 virtual 下可用
onSourceScrolledBottom 源数据列表滚动到底部时触发 () => void - - 仅使用默认列表并开启 virtual 下可用
onSourceScroll 目标列表滚动事件 (evt: Event) => void - - 仅使用默认列表并开启 virtual 下可用
onSourceScrolledChange 目标列表滚动的位置发生变化 (startIndex: number, endIndex: number, visibleNodes: unknown[]) => void - - 仅使用默认列表并开启 virtual 下可用
onSourceScrolledBottom 目标列表滚动到底部时触发 () => void - - 仅使用默认列表并开启 virtual 下可用
customLabel 自定义数据 label 渲染 string \| (item: unknown) => VNodeChild - - 仅使用默认列表时可用
listStyle 自定义列表样式 - - - 仅使用默认列表时可用
searchable 是否可搜索 boolean true 仅使用默认列表头部时可用
v-model:searchValue 搜索框内容 string | undefined - 仅使用默认列表头部时可用
searchPlaceholder 搜索框placeholder string '搜索关键字' - 仅使用默认列表头部时可用
sourcePagination 源数据列表分页配置 boolean \| PaginationProps false 仅使用默认列表底部时可用
targetPagination 目标数据列表分页配置 boolean \| PaginationProps false 仅使用默认列表底部时可用
showOperations 是否展示左右穿梭箭头 boolean true 不展示穿梭箭头时以勾选作为选中
showListHeader 是否展示列表头部 boolean true -
showListFooter 是否展示列表底部 boolean false -
showCheckAll 是否展示全选框 boolean true -
onSelectChange 穿梭框数据改变回调函数 (data: unknown[]) => void - - -
onSearchChange 穿梭框搜索输入回调函数 (searchValue: string | undefined) => void - - -
onSourceCheckAll 源数据列表全部勾选回调函数 (checked: boolean) => void - - -
onTargetCheckAll 目标数据列表全部勾选回调函数 (checked: boolean) => void - - -
onSourceNodeClick 源数据列表数据项点击回调 (evt: Event, item: unknown) => void - - 仅使用默认列表底部时可用
onTargetNodeClick 目标数据列表数据项点击回调 (evt: Event, item: unknown) => void - - 仅使用默认列表底部时可用
onSourceNodeContextmenu 源数据列表数据右键列表回调 (evt: Event, item: unknown) => void - - 仅使用默认列表底部时可用
onTargetNodeContextmenu 目标数据列表数据右键列表回调 (evt: Event, item: unknown) => void - - 仅使用默认列表底部时可用

TransferSlots

名称 说明 参数类型 备注
default 穿梭框列表主体 TransferBindings & { isSource: boolean } -
header 穿梭框列表头部 TransferBindings & { isSource: boolean } -
footer 穿梭框列表底部 TransferBindings & { isSource: boolean } -

TransferMethods

名称 说明 参数类型 备注
sourceScrollTo 源数据滚动到指定位置 (option?: number \| VirtualScrollToOptions) => void 仅使用默认列表并开启 virtual 下可用
targetScrollTo 目标数据滚动到指定位置 (option?: number \| VirtualScrollToOptions) => void 仅使用默认列表并开启 virtual 下可用

Tokens

TRANSFER_SOURCE_TOKEN

可以结合插槽注入该 token 来获取自定义源数据穿梭框所需要的API与参数

export const TRANSFER_SOURCE_TOKEN: InjectionKey<TransferBindings> = Symbol('TRANSFER_SOURCE_TOKEN')

TRANSFER_TARGET_TOKEN

可以结合插槽注入该 token 来获取自定义源数据穿梭框所需要的API与参数

export const TRANSFER_TARGET_TOKEN: InjectionKey<TransferBindings> = Symbol('TRANSFER_TARGET_TOKEN')

TRANSFER_DATA_STRATEGIES

可以通过该 token 注入自定义的数据处理逻辑来自定义穿梭框,例如自定义树形数据的处理逻辑

export interface SeparatedData<T = unknown> {
  sourceData: T[]
  targetData: T[]
}
export interface TransferDataStrategies<T = unknown> {
  genDataKeys: (data: T[], getRowKey: GetRowKey) => Set<VKey>
  genDataKeyMap: (dataSource: T[], getRowKey: GetRowKey) => Map<VKey, T>
  separateDataSource: (
    dataSource: T[],
    selectedData: T[],
    selectedKeys: Set<VKey>,
    getRowKey: GetRowKey,
  ) => SeparatedData<T>
  checkDisabled: (item: T, dataSource: T[], itemDisabled: ((item: T) => boolean) | undefined) => boolean
  dataFilter: (data: T[], searchValue: string | undefined, searchFn: SearchFn<T> | undefined) => T[]
  appendSelectedData: (
    data: T[],
    selectedData: T[],
    selectedKeys: Set<VKey>,
    getRowKey: GetRowKey,
    setSelectedData: (value: T[]) => void,
  ) => void
  removeSelectedData: (
    keys: VKey[],
    selectedData: T[],
    selectedKeys: Set<VKey>,
    getRowKey: GetRowKey,
    setSelectedData: (value: T[]) => void,
  ) => void
}
export const TRANSFER_DATA_STRATEGIES: InjectionKey<TransferDataStrategies | null> = Symbol('TRANSFER_DATA_STRATEGIES')
danranVm commented 2 years ago
export interface TransferData {
key?: VKey
label?: string
disabled?: boolean
additional?: {
    class?: any
    style?: any
    [key: string]: unknown
  }
}

其他的一些 API,例如 methods, 或者对外暴露的 token 的内容,你再仔细斟酌一下。