Skip to content

useTableSelection

表格行选择管理 Composable,提供统一的表格选择逻辑。

功能介绍

useTableSelection 封装了表格多选的常用逻辑:

  • 管理选中的 ID 列表
  • 处理选择变化事件
  • 清空选择
  • 检查是否选中
  • 获取选中数量

基本用法

vue
<template>
  <el-table
    :data="tableData"
    @selection-change="handleSelectionChange"
  >
    <el-table-column type="selection" width="50" />
    <el-table-column prop="name" label="姓名" />
    <el-table-column prop="email" label="邮箱" />
  </el-table>
  
  <div class="toolbar">
    <span>已选择 {{ selectedCount }} 条</span>
    <el-button 
      :disabled="!hasSelection" 
      @click="handleBatchDelete"
    >
      批量删除
    </el-button>
    <el-button @click="clearSelection">清空选择</el-button>
  </div>
</template>

<script setup lang="ts">
import { useTableSelection } from '@/composables'

interface UserVO {
  id: number
  name: string
  email: string
}

const tableData = ref<UserVO[]>([])

const {
  selectedIds,
  selectedCount,
  hasSelection,
  handleSelectionChange,
  clearSelection
} = useTableSelection<UserVO>()

async function handleBatchDelete() {
  if (!hasSelection.value) {
    ElMessage.warning('请选择要删除的数据')
    return
  }
  
  await UserAPI.deleteByIds(selectedIds.value)
  ElMessage.success('删除成功')
  clearSelection()
  fetchData()
}
</script>

类型定义

typescript
function useTableSelection<T extends { id: string | number }>(): {
  /** 选中的 ID 列表 */
  selectedIds: Ref<(string | number)[]>
  
  /** 选中的数量 */
  selectedCount: ComputedRef<number>
  
  /** 是否有选中项 */
  hasSelection: ComputedRef<boolean>
  
  /** 处理选择变化 */
  handleSelectionChange: (selection: T[]) => void
  
  /** 清空选择 */
  clearSelection: () => void
  
  /** 检查指定 ID 是否被选中 */
  isSelected: (id: string | number) => boolean
}

返回值

名称类型说明
selectedIdsRef<(string | number)[]>选中的 ID 数组
selectedCountComputedRef<number>选中的数量
hasSelectionComputedRef<boolean>是否有选中项
handleSelectionChange(selection: T[]) => void处理选择变化
clearSelection() => void清空选择
isSelected(id) => boolean检查是否选中

泛型约束

数据项类型必须包含 id 属性:

typescript
// ✅ 正确
interface UserVO {
  id: number
  name: string
}

const { selectedIds } = useTableSelection<UserVO>()

// ❌ 错误:缺少 id 属性
interface Item {
  name: string
}

const { selectedIds } = useTableSelection<Item>() // 类型错误

配合 CURD 组件使用

vue
<template>
  <page-content
    ref="contentRef"
    :content-config="contentConfig"
    @selection-change="handleSelectionChange"
  />
  
  <el-button 
    :disabled="!hasSelection"
    @click="handleBatchExport"
  >
    导出选中 ({{ selectedCount }})
  </el-button>
</template>

<script setup lang="ts">
import { useTableSelection } from '@/composables'

const {
  selectedIds,
  selectedCount,
  hasSelection,
  handleSelectionChange,
  clearSelection
} = useTableSelection()

async function handleBatchExport() {
  await exportData(selectedIds.value)
  clearSelection()
}
</script>

高级用法

自定义主键字段

如果数据的主键不是 id,可以在处理函数中转换:

typescript
interface OrderVO {
  orderId: string
  orderNo: string
}

const selectedOrderIds = ref<string[]>([])

function handleSelectionChange(selection: OrderVO[]) {
  selectedOrderIds.value = selection.map(item => item.orderId)
}

跨页选择

配合表格的 row-keyreserve-selection 实现跨页选择:

vue
<template>
  <el-table
    :data="tableData"
    :row-key="row => row.id"
    @selection-change="handleSelectionChange"
  >
    <el-table-column 
      type="selection" 
      width="50"
      :reserve-selection="true"
    />
  </el-table>
</template>

注意事项

  1. 泛型类型:确保传入的泛型类型包含 id 属性
  2. 清空时机:删除或其他操作后记得调用 clearSelection()
  3. 响应式selectedIds 是响应式的,可以直接在模板中使用

相关链接

基于 MIT 许可发布