跳转到内容

ProList / BaseProList ​

用列表展示 schema 数据,复用 ProTable 的请求、查询、分页、工具栏、选择和编辑能力。BaseProList 提供更轻的默认外观。

vue
<script setup lang="ts">
import { computed, h, ref } from 'vue'
import { Button, Space } from 'antdv-next'
import {
  BaseProList,
  ProList,
  type ProKey,
  type ProListMetas,
  type ProTableInstance,
} from '@bubblesjs/antv-next-pro'

interface Project extends Record<string, unknown> {
  id: number
  name: string
  description: string
  owner: string
  status: string
}

const projects: Project[] = [
  {
    id: 1,
    name: '组件文档',
    description: '整理组件用法与可运行示例。',
    owner: '林晓',
    status: 'active',
  },
  {
    id: 2,
    name: '主题配置',
    description: '统一颜色、间距与深色主题。',
    owner: '陈雨',
    status: 'active',
  },
  {
    id: 3,
    name: '发布准备',
    description: '核对类型声明与迁移说明。',
    owner: '周宁',
    status: 'done',
  },
  {
    id: 4,
    name: '交互验收',
    description: '验证搜索、选择和展开行为。',
    owner: '许舟',
    status: 'pending',
  },
]
const action = ref<ProTableInstance<Project>>()
const selectedKeys = ref<ProKey[]>([])
const requestCount = ref(0)
const feedback = ref('点击详情、勾选项目,或展开一条记录。')
const selection = computed(() => ({
  selectedRowKeys: selectedKeys.value,
  onChange: (keys: ProKey[]) => {
    selectedKeys.value = keys
  },
}))
const metas: ProListMetas<Project> = {
  title: { title: '项目名称', dataIndex: 'name' },
  subTitle: {
    dataIndex: 'status',
    search: false,
    valueEnum: {
      active: { text: '进行中', status: 'Processing' },
      done: { text: '已完成', status: 'Success' },
      pending: { text: '待开始', status: 'Default' },
    },
  },
  description: { dataIndex: 'description', search: false },
  actions: {
    search: false,
    render: (_dom, record) =>
      h(
        Button,
        {
          type: 'link',
          'data-demo-list-details': String(record.id),
          onClick: () => {
            feedback.value = `${record.name} · 负责人:${record.owner}`
          },
        },
        () => '查看详情',
      ),
  },
}

async function request(params: Record<string, unknown>) {
  requestCount.value++
  const keyword = typeof params.name === 'string' ? params.name.trim() : ''
  const filtered = projects.filter((item) => item.name.includes(keyword))
  const current = Number(params.current ?? 1)
  const pageSize = Number(params.pageSize ?? 2)
  return {
    data: filtered.slice((current - 1) * pageSize, current * pageSize),
    total: filtered.length,
    success: true,
  }
}
</script>

<template>
  <div class="list-demo" data-demo="pro-list">
    <ProList
      ref="action"
      header-title="项目列表"
      row-key="id"
      :metas="metas"
      :request="request"
      :search="{ defaultCollapsed: false, searchText: '搜索项目' }"
      :pagination="{ defaultPageSize: 2, showSizeChanger: false }"
      :row-selection="selection"
      :expandable="{
        expandedRowRender: (record: Project) => `负责人:${record.owner}。${record.description}`,
      }"
      :classes="{ title: 'project-title' }"
    >
      <template #toolbar-actions>
        <Space>
          <Button data-demo-list-reload @click="action?.reload()">重新加载</Button>
          <Button :disabled="!selectedKeys.length" @click="selectedKeys = []">清除选择</Button>
        </Space>
      </template>
    </ProList>
    <p data-demo-list-state aria-live="polite">
      已选 {{ selectedKeys.length }} 项 · 请求 {{ requestCount }} 次。{{ feedback }}
    </p>

    <section aria-label="基础卡片列表">
      <h3>BaseProList:独立卡片列表</h3>
      <p>复用相同的字段映射,按屏幕宽度显示一列或两列。</p>
      <BaseProList
        row-key="id"
        :data-source="projects.slice(0, 2)"
        :metas="{ title: metas.title, subTitle: metas.subTitle, description: metas.description }"
        :grid="{ gutter: 20, xs: 1, md: 2 }"
        :split="false"
        :on-item="
          (record: Project) => ({
            tabindex: 0,
            'data-demo-list-card': record.id,
            onClick: () => {
              feedback = `当前卡片:${record.name}`
            },
            onKeydown: (event: KeyboardEvent) => {
              if (event.key === 'Enter') feedback = `当前卡片:${record.name}`
            },
          })
        "
        :styles="{
          row: {
            padding: '20px',
            border: '1px solid #d9d9d9',
            borderRadius: '8px',
            cursor: 'pointer',
          },
        }"
      />
    </section>
  </div>
</template>

<style scoped>
.list-demo {
  display: grid;
  gap: 20px;
}
h3 {
  margin-block: 0 8px;
}
p {
  margin: 0;
  color: inherit;
}
:deep(.project-title) {
  font-weight: 600;
}
</style>

最小用法 ​

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

type Project = { id: number; name: string; description: string }
const rows = ref<Project[]>([
  { id: 1, name: '组件库', description: '统一业务组件与主题' },
  { id: 2, name: '工作台', description: '整理日常工作' },
])
const metas: ProListMetas<Project> = {
  title: { dataIndex: 'name', title: '名称' },
  description: { dataIndex: 'description' },
}
</script>

<template>
  <ProList row-key="id" :data-source="rows" :metas="metas" />
</template>

数据与 schema ​

columns 与 metas 选择一种即可,显式 columns 优先。metas 使用区域名组织字段;对应的 columns 通过 listSlot 指定区域。

区域用途
title / subTitle标题、副标题
avatar头像,默认 valueType="avatar"
description / content描述、正文
actions操作,默认 valueType="option"
extra右侧附加内容

各项继承 ProColumns<T>,支持 valueType、valueEnum、fieldProps、远程选项和字段格式化。省略 dataIndex 时使用区域名;其他区域默认 valueType="text"。

render 使用 v3 签名 (dom, record, index, action, schema),首参是默认渲染节点。需要原始字段值时使用 record 或先在 renderText(value, record, index, action) 中处理。

API ​

属性说明
dataSource / defaultDataSource / request / params继承 ProTable 的受控、本地和远程数据方式;请求返回 { data, total?, success? }
rowKey唯一记录标识,推荐显式设置
columns / metasProListColumn<T>[] / ProListMetas<T>
grid{ gutter?, column?, xs?, sm?, md?, lg?, xl?, xxl? };数字表示每行项数
itemLayouthorizontal / vertical
split是否显示分隔线,默认显示
showActions / showExtraalways / hover;悬停模式也在键盘焦点进入行时显示
itemRender(record, index, defaultDom) => VNodeChild,替换整项
itemTitleRender / itemHeaderRender同上,分别替换标题、头部;false 隐藏该区域
onItem / onRow(record, index) => HTMLAttributes,合并绑定到列表行
rowClassName字符串或 (record, index) => string
rowSelection继承 ProTable 的选择配置,支持受控 key、单选/多选和禁用项
expandable展开配置,支持受控 key、展开事件及 expandedRowRender
prefixCls / classes / styles前缀与语义样式,见下文

ProList 默认关闭 search、options、pagination,可显式开启;其他工具栏、请求和编辑属性参见 ProTable。BaseProList 在此基础上默认设置 cardProps=false、search=false、toolBarRender=false,这些默认值均可覆盖。

启用 grid 时,每项使用现有 ProCard 呈现,itemCardProps 传入卡片属性。操作 schema(如 metas.actions)的 cardActionProps="actions" 将操作放在卡片底部;extra 或省略时放在卡片头部附加区域。grid 的断点数值决定每行卡片数。

事件、插槽与实例 ​

数据、分页、选择、编辑事件沿用 ProTable;受控 dataSource 的回传使用 v-model:dataSource。选择变化通过 rowSelection.onChange 接收,展开变化通过 expandable 的回调接收。

插槽参数
title / description / content / extra / actions{ record, index },替换对应列表区域
expandedRowRender{ record, index },替换展开正文
ProTable 插槽同时转发给外层表格框架;名称可能与列表区域重合,作用域需按实际位置处理

组件 ref 为 ProTableInstance<T>:支持 reload、reset、setPageInfo、clearSelected、getRowData、getRowsData、setRowData,以及 startEditable、saveEditable、cancelEditable 等方法。BaseProList 转发同一实例能力。

样式与配置 ​

classes / styles 支持对象或 ({ props }) => map。列表消费的部位为 root、container、row、header、title、subTitle、description、content、extra、actions、expanded。旧 classNames 兼容,同名部位 classes 优先。

默认公开前缀为 ant-pro-list;原生 ConfigProvider 设置 prefixCls="demo" 后为 demo-pro-list。prefixCls 可覆盖当前列表前缀。语言、方向、主题算法、全局及原生组件 token 继承原生 ConfigProvider,Pro 扩展 token 使用 ProConfigProvider 的 token。

使用边界 ​

列表呈现 listSlot 对应的区域;任意其他 schema 键不会自动生成独立区域。itemCardProps 与 cardActionProps 用于网格卡片布局,普通列表使用自身操作区域。fullScreen、scrollTo 等继承方法的实际作用范围由外层 ProTable 决定。

基于 MIT 许可发布