跳转到内容

表格增强 ​

DragSortTable、RowEditorTable、CellEditorTable 复用 ProTable 的 schema、数据请求、原生配置与语义样式,分别提供拖拽排序、整行编辑、单元格编辑。

vue
<script setup lang="ts">
import { ref } from 'vue'
import { Button, Space } from 'antdv-next'
import {
  CellEditorTable,
  DragSortTable,
  RowEditorTable,
  type EditableConfig,
  type ProColumns,
  type ProKey,
  type ProTableInstance,
} from '@bubblesjs/antv-next-pro'

interface Task extends Record<string, unknown> {
  id: number
  name: string
  priority: number
}
const initial: Task[] = [
  { id: 1, name: '编写示例', priority: 1 },
  { id: 2, name: '交互验收', priority: 2 },
  { id: 3, name: '整理文档', priority: 3 },
]
const columns: ProColumns<Task>[] = [
  {
    title: '任务',
    dataIndex: 'name',
    formItemProps: { rules: [{ required: true, message: '请输入任务名称' }] },
  },
  { title: '优先级', dataIndex: 'priority', valueType: 'digit', fieldProps: { min: 1, max: 5 } },
]
const dragRows = ref(initial.map((row) => ({ ...row })))
const rowRows = ref(initial.map((row) => ({ ...row })))
const cellRows = ref(initial.map((row) => ({ ...row })))
const rowAction = ref<ProTableInstance<Task>>()
const cellAction = ref<ProTableInstance<Task>>()
const feedback = ref('拖动手柄排序;也可以聚焦手柄后按上下方向键。')
const editable: EditableConfig<Task> = {
  type: 'single',
  onSave: async (_key, record) => {
    feedback.value = `已保存任务:${record.name}`
    return true
  },
}
function dragEnd(from: number, to: number, rows: Task[]) {
  feedback.value = `第 ${from + 1} 项移至第 ${to + 1} 项;当前顺序:${rows.map((row) => row.name).join('、')}`
}
function begin(_key: ProKey, record: Task) {
  feedback.value = `正在编辑:${record.name}`
}
function end(_key: ProKey, record: Task) {
  feedback.value = `编辑结束:${record.name}`
}
</script>

<template>
  <div class="enhanced-demo" data-demo="table-enhancements">
    <section data-demo-drag-table>
      <h3>拖动排序</h3>
      <p>拖动行首手柄,或聚焦手柄后按 ↑ / ↓。排序结果保存在当前页面。</p>
      <DragSortTable
        v-model:data-source="dragRows"
        row-key="id"
        :columns="columns"
        :search="false"
        :options="false"
        :pagination="false"
        :tool-bar-render="false"
        @drag-sort-end="dragEnd"
      />
    </section>
    <section data-demo-row-table>
      <h3>行编辑</h3>
      <p>双击一行进入编辑,焦点离开当前行后保存;按钮也可启动、保存和取消。</p>
      <Space class="actions">
        <Button data-demo-row-start @click="rowAction?.startEditable(1)">编辑第一行</Button>
        <Button data-demo-row-save @click="rowAction?.saveEditable(1)">保存第一行</Button>
        <Button data-demo-row-cancel @click="rowAction?.cancelEditable(1)">取消编辑</Button>
      </Space>
      <RowEditorTable
        ref="rowAction"
        v-model:data-source="rowRows"
        row-key="id"
        :columns="columns"
        :editable="editable"
        :search="false"
        :options="false"
        :pagination="false"
        :tool-bar-render="false"
        :on-row-edit-start="begin"
        :on-row-edit-end="end"
      />
    </section>
    <section data-demo-cell-table>
      <h3>单元格编辑</h3>
      <p>双击名称或优先级,只编辑当前单元格;切换单元格时先保存并校验。</p>
      <Space class="actions">
        <Button data-demo-cell-start @click="cellAction?.startEditable(1)">编辑首个单元格</Button>
        <Button data-demo-cell-save @click="cellAction?.saveEditable(1)">保存第一行</Button>
        <Button data-demo-cell-cancel @click="cellAction?.cancelEditable(1)">取消编辑</Button>
      </Space>
      <CellEditorTable
        ref="cellAction"
        v-model:data-source="cellRows"
        row-key="id"
        :columns="columns"
        :editable="editable"
        :search="false"
        :options="false"
        :pagination="false"
        :tool-bar-render="false"
        :on-row-edit-start="begin"
        :on-row-edit-end="end"
      />
    </section>
    <p data-demo-enhanced-state aria-live="polite">{{ feedback }}</p>
  </div>
</template>

<style scoped>
.enhanced-demo {
  display: grid;
  gap: 28px;
}
h3 {
  margin-block: 0 8px;
}
p {
  margin-block: 0 16px;
}
.actions {
  margin-block-end: 12px;
}
</style>

最小用法 ​

vue
<script setup lang="ts">
import { ref } from 'vue'
import { DragSortTable, type ProColumns } from '@bubblesjs/antv-next-pro'

type Task = { id: number; title: string }
const rows = ref<Task[]>([
  { id: 1, title: '整理需求' },
  { id: 2, title: '验证实现' },
])
const columns: ProColumns<Task>[] = [{ title: '任务', dataIndex: 'title' }]
</script>

<template>
  <DragSortTable
    v-model:dataSource="rows"
    row-key="id"
    :columns="columns"
    :search="false"
    :pagination="false"
  />
</template>

DragSortTable ​

继承 ProTable 属性与 ProTableInstance<T>。泛型为记录类型 T 与请求参数类型 P。

属性/事件说明
dragSortKey排序列 key 或 dataIndex,默认 __dragSort;不存在该列时在开头插入手柄列
dragSortHandlerRender(record, index) => VNodeChild,定制手柄内部内容
v-model:dataSource受控数据;调用方接收新数组后完成排序
defaultDataSource非受控初始数据
dragSortEnd(beforeIndex, afterIndex, rows)排序完成通知,携带调整后的完整记录数组
dataSourceChange(rows)数据顺序变化通知

手柄支持拖拽和键盘上下方向键。排序事件中的下标指向当前数据源中的位置;通过分页展示时不要将其当成数据库的永久排序编号。受控模式不会绕过父组件更新数据;异步持久化由调用方在事件中处理,返回 Promise 不代表组件自动回滚。

手柄默认类名为 ant-pro-table-drag-icon,随原生全局前缀和组件前缀变化。

RowEditorTable ​

继承 EditableProTable,双击行进入编辑,焦点离开该行后等待 150ms 再校验并保存。焦点仍在同一行内移动时不会触发保存。默认 editable.type="single",默认关闭新建行按钮;可用显式配置覆盖。

属性/事件说明
editable继承编辑配置:校验、onSave、onCancel、editableKeys、formRef 等
onRowEditStart(key, record)进入编辑时调用
onRowEditEnd(key, record)保存成功、取消或编辑 key 移除时调用
onRow原生行绑定;原有双击回调先执行,调用 event.preventDefault() 可阻止自动进入
v-model:editableKeys继承受控编辑 key 回传

editable.onSave 返回 false 或字段校验失败时保留编辑状态。editable.formRef 提供实际原生 FormInstance。dataSource、value、编辑结果回传等数据约定见 EditableProTable。

CellEditorTable ​

继承 RowEditorTable 的配置和回调。双击可编辑单元格,只将当前单元格切换为输入;焦点离开单元格 150ms 后保存。双击其他单元格时先保存当前编辑,校验失败会阻止切换。

readonly、editable=false、valueType="option" 列不能进入单元格编辑。column.onCell 的原有双击回调先执行,可使用 event.preventDefault() 阻止激活。程序调用 startEditable(key) 时选择该行第一个允许编辑的字段。

插槽、实例与样式 ​

三个组件转发底层表格插槽及 ProTableInstance<T>:请求刷新、数据读写、分页、选择,以及 startEditable(key)、saveEditable(key)、cancelEditable(key) 等。Row/Cell 的实例编辑方法同时维护各自的编辑生命周期回调。

列 render 统一为 (dom, record, index, action, schema),自定义编辑使用 formItemRender(schema, context, nativeForm)。字段规则由原生 Form 验证。

prefixCls、classes、styles 沿用底层 ProTable/EditableProTable;classes / styles 接受对象或 ({ props }) => map,旧 classNames 兼容。语言、RTL、原生 theme 及 Pro 扩展 token 沿用 ProConfigProvider 约定。

使用边界 ​

Row/Cell 自动保存依赖双击和焦点离开,可用实例方法提供显式编辑入口。150ms 是焦点缓冲时间,不是网络保存完成时间;应在 editable.onSave 中返回实际保存 Promise。DragSortTable 调整当前数据顺序;跨页远程排序和服务端排名由业务维护。

基于 MIT 许可发布