Skip to content

ProList / BaseProList ​

A schema-driven list that shares ProTable requests, search, pagination, toolbar, selection and editing. BaseProList provides lighter presentation defaults.

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>

Minimal usage ​

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: 'Components', description: 'Shared components and themes' },
  { id: 2, name: 'Workspace', description: 'Organize daily work' },
])
const metas: ProListMetas<Project> = {
  title: { dataIndex: 'name', title: 'Name' },
  description: { dataIndex: 'description' },
}
</script>

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

Data and schema ​

Choose columns or metas; explicit columns take precedence. Metas map region names to schemas. Columns use listSlot to select a region.

RegionPurpose
title / subTitleTitle and subtitle
avatarAvatar, default valueType is avatar
description / contentDescription and main content
actionsActions, default valueType is option
extraAdditional content on the side

Each entry extends ProColumns<T> and supports valueType, valueEnum, fieldProps, remote options and field formatting. The region name is the default dataIndex. Other regions default to text.

The v3 renderer is (dom, record, index, action, schema): the first argument is the default node. Read raw values from record or transform them in renderText(value, record, index, action).

API ​

PropBehavior
dataSource / defaultDataSource / request / paramsProTable controlled, local and remote data; request returns { data, total?, success? }
rowKeyStable record identifier; set it explicitly
columns / metasProListColumn<T>[] / ProListMetas<T>
grid{ gutter?, column?, xs?, sm?, md?, lg?, xl?, xxl? }; numbers specify items per row
itemLayouthorizontal or vertical
splitDividers, enabled by default
showActions / showExtraalways or hover; hover content also appears on keyboard focus within the row
itemRender(record, index, defaultDom) => VNodeChild, replaces the entire item
itemTitleRender / itemHeaderRenderThe same signature for the title or header; false hides that region
onItem / onRow(record, index) => HTMLAttributes, merged onto the list row
rowClassNameString or (record, index) => string
rowSelectionProTable selection configuration, including controlled keys, radio/checkbox and disabled items
expandableControlled expansion, callbacks and expandedRowRender
prefixCls / classes / stylesPrefix and semantic styles

ProList disables search, options and pagination by default; pass explicit configurations to enable them. Other request, toolbar and editing props follow ProTable. BaseProList additionally defaults cardProps, search and toolBarRender to false; each default can be overridden.

With grid enabled, each item uses the existing ProCard. Pass card props through itemCardProps. Set cardActionProps="actions" on the actions schema, such as metas.actions, to place actions in the card footer; extra or an omitted value places them in the header extra region. Grid breakpoint numbers specify cards per row.

Events, slots and ref ​

Data, pagination and editing events follow ProTable. Use v-model:dataSource for controlled data, rowSelection.onChange for selection, and expandable callbacks for expansion.

SlotScope
title / description / content / extra / actions{ record, index }, replaces that list region
expandedRowRender{ record, index }, replaces expanded content
ProTable slotsAlso forwarded to the outer table framework; shared names may receive scopes from both rendering positions

The component ref exposes ProTableInstance<T>, including reload, reset, setPageInfo, clearSelected, getRowData, getRowsData, setRowData, startEditable, saveEditable and cancelEditable. BaseProList forwards the same instance API.

Styling and configuration ​

Classes/styles accept a map or ({ props }) => map. Consumed list parts are root, container, row, header, title, subTitle, description, content, extra, actions and expanded. Legacy classNames remains compatible; classes wins for matching parts.

The default public prefix is ant-pro-list. A native ConfigProvider with prefixCls="demo" produces demo-pro-list; the list prefixCls can override it. Locale, direction, theme algorithms, global tokens and native component tokens follow ConfigProvider. Configure Pro extension tokens through ProConfigProvider.token.

Boundaries ​

Only supported listSlot regions are rendered; arbitrary schema keys do not create extra regions. ItemCardProps and cardActionProps target grid cards; regular lists use their own action region. Inherited methods such as fullScreen and scrollTo act through the surrounding ProTable.

Released under the MIT License