树形表格用于以表格格式显示分层数据。
import TreeTable from 'primevue/treetable';
import Column from 'primevue/column';
树形表格需要 TreeNode 实例的集合作为 value,以及 Column 组件作为子项进行表示。带有切换节点元素的列应启用 expander。
<TreeTable :value="nodes" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>
可以以编程方式创建列。
<TreeTable :value="nodes" tableStyle="min-width: 50rem">
<Column v-for="col of columns" :key="col.field" :field="col.field" :header="col.header" :expander="col.expander"></Column>
</TreeTable>
使用 expandedKeys 属性控制展开状态。expandedKeys 应该是一个对象,其键引用节点键,值表示展开状态,例如 {'0-0': true}。
<Button @click="toggleApplications" label="Toggle Applications" />
<TreeTable v-model:expandedKeys="expandedKeys" :value="nodes" class="mt-6" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>
通过模板支持 header 和 footer 插槽处的自定义内容。
<TreeTable :value="nodes" tableStyle="min-width: 50rem">
<template #header>
<div class="text-xl font-bold">File Viewer</div>
</template>
<Column field="name" header="Name" expander style="width: 250px"></Column>
<Column field="size" header="Size" style="width: 150px"></Column>
<Column field="type" header="Type" style="width: 150px"></Column>
<Column style="width: 10rem">
<template #body>
<div class="flex flex-wrap gap-2">
<Button type="button" icon="pi pi-search" rounded />
<Button type="button" icon="pi pi-pencil" rounded severity="success" />
</div>
</template>
</Column>
<template #footer>
<div class="flex justify-start">
<Button icon="pi pi-refresh" label="Reload" severity="warn" />
</div>
</template>
</TreeTable>
除了常规表格外,还提供具有替代大小的替代方案。
<TreeTable :value="nodes" :size="size.value" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>
通过添加 paginator 属性并定义每页 rows 来启用分页。
<TreeTable :value="nodes" :paginator="true" :rows="5" :rowsPerPageOptions="[5, 10, 25]" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>
使用 paginatorTemplate 属性自定义分页器 UI。每个元素还可以使用您自己的 UI 进行进一步自定义以替换默认的 UI,有关高级自定义选项的更多信息,请参阅 分页器 组件。
<TreeTable
:value="nodes"
:paginator="true"
:rows="5"
:rowsPerPageOptions="[5, 10, 25, 50]"
paginatorTemplate="RowsPerPageDropdown FirstPageLink PrevPageLink CurrentPageReport NextPageLink LastPageLink"
currentPageReportTemplate="{first} to {last} of {totalRecords}"
tableStyle="min-width: 50rem"
>
<template #paginatorstart>
<Button type="button" icon="pi pi-refresh" text />
</template>
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
<template #paginatorend>
<Button type="button" icon="pi pi-download" text />
</template>
</TreeTable>
通过添加 paginator 属性并定义每页 rows 来启用分页。
<TreeTable :value="nodes" :paginator="true" :rows="5" :rowsPerPageOptions="[5, 10, 25]" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
<template #paginatorcontainer="{ first, last, page, pageCount, prevPageCallback, nextPageCallback, totalRecords }">
<div class="flex items-center gap-4 border border-primary bg-transparent rounded-full w-full py-1 px-2 justify-between">
<Button icon="pi pi-chevron-left" rounded text @click="prevPageCallback" :disabled="page === 0" />
<div class="text-color font-medium">
<span class="hidden sm:block">Showing {{ first }} to {{ last }} of {{ totalRecords }}</span>
<span class="block sm:hidden">Page {{ page + 1 }} of {{ pageCount }}</span>
</div>
<Button icon="pi pi-chevron-right" rounded text @click="nextPageCallback" :disabled="page === pageCount - 1" />
</div>
</template>
</TreeTable>
通过添加 sortable 属性启用列的排序。
<TreeTable :value="nodes" tableStyle="min-width: 50rem">
<Column field="name" header="Name" sortable expander style="width: 34%"></Column>
<Column field="size" header="Size" sortable style="width: 33%"></Column>
<Column field="type" header="Type" sortable style="width: 33%"></Column>
</TreeTable>
可以通过将 sortMode 定义为 multiple 来对多列进行排序。此模式需要在单击标题时按下元键(例如 ⌘)。
<TreeTable :value="nodes" sortMode="multiple" tableStyle="min-width: 50rem">
<Column field="name" header="Name" sortable expander style="width: 34%"></Column>
<Column field="size" header="Size" sortable style="width: 33%"></Column>
<Column field="type" header="Type" sortable style="width: 33%"></Column>
</TreeTable>
当存在 removableSort 时,第三次单击会从列中删除排序。
<TreeTable :value="nodes" sortMode="multiple" removableSort tableStyle="min-width: 50rem">
<Column field="name" header="Name" sortable expander style="width: 34%"></Column>
<Column field="size" header="Size" sortable style="width: 33%"></Column>
<Column field="type" header="Type" sortable style="width: 33%"></Column>
</TreeTable>
通过向列添加 filter 属性来启用筛选。filterMode 指定筛选策略,在 lenient 模式下,当查询匹配一个节点时,不会进一步搜索该节点的子节点,因为该节点的所有后代都包含在内。另一方面,在 strict 模式下,当查询匹配一个节点时,筛选会继续对所有后代进行。
<SelectButton v-model="filterMode" optionLabel="label" dataKey="label" :options="filterOptions" />
<TreeTable :value="nodes" :filters="filters" :filterMode="filterMode.value">
<template #header>
<div class="flex justify-end">
<IconField>
<InputIcon class="pi pi-search" />
<InputText v-model="filters['global']" placeholder="Global Search" />
</IconField>
</div>
</template>
<Column field="name" header="Name" expander style="min-width: 12rem">
<template #filter>
<InputText v-model="filters['name']" type="text" placeholder="Filter by name" />
</template>
</Column>
<Column field="size" header="Size" style="min-width: 12rem">
<template #filter>
<InputText v-model="filters['size']" type="text" placeholder="Filter by size" />
</template>
</Column>
<Column field="type" header="Type" style="min-width: 12rem">
<template #filter>
<InputText v-model="filters['type']" type="text" placeholder="Filter by type" />
</template>
</Column>
</TreeTable>
通过将 selectionMode 设置为 single 以及 selectionKeys 属性来管理选择值绑定,从而配置单节点选择。
默认情况下,需要按元键(例如 ⌘)来取消选择一个节点,但是可以通过禁用 metaKeySelection 属性来配置此选项。在支持触摸的设备中,此选项不起作用,其行为与将其设置为 false 相同。
<ToggleSwitch v-model="metaKey" inputId="input-metakey" />
<TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="single" :metaKeySelection="metaKey" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>
通过将 selectionMode 设置为 multiple,可以选择多个节点。默认情况下,在多选模式下,不需要按元键(例如 ⌘)添加到现有选择中。当存在可选的 metaKeySelection 时,其行为会发生更改,即选择新节点需要存在元键。请注意,在支持触摸的设备中,树形表格始终忽略元键。
在多选模式下,值绑定应为键值对,其中键是节点键,值是一个布尔值,用于指示选择。
<ToggleSwitch v-model="metaKey" inputId="input-metakey" />
<TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="multiple" :metaKeySelection="metaKey" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>
通过将 selectionMode 配置为 checkbox,可以通过复选框选择多个节点。
在复选框选择模式下,值绑定应为键值对,其中键(或 dataKey)是节点键,值是一个对象,该对象具有 checked 和 partialChecked 属性来表示节点的选中状态。
{
'0-0': {
partialChecked: false,
checked: true
}
}
<TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="checkbox" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>
树形表格提供 nodeSelect 和 nodeUnselect 事件来监听选择事件。
<TreeTable v-model:selectionKeys="selectedKey" :value="nodes" selectionMode="single" @nodeSelect="onNodeSelect" @nodeUnselect="onNodeUnselect" :metaKeySelection="false" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>
延迟模式可方便地处理大型数据集,而不是加载整个数据,每次发生 paging、sorting 和 filtering 时,都会通过调用相应的回调来加载小块数据。下面的示例使用内存列表和超时来模拟网络连接,从而模拟从远程数据源延迟加载数据。
启用 lazy 属性并通过执行投影查询将逻辑行数分配给 totalRecords 是实现的关键要素,以便分页器显示 UI,假设实际上存在 totalRecords 大小的记录,但实际上它们并不存在于页面上,只存在当前页面上显示的记录。
此外,应该只加载根元素,可以使用 nodeExpand 回调按需加载子元素。
<TreeTable :value="nodes" :lazy="true" :paginator="true" :rows="rows" :loading="loading"
@nodeExpand="onExpand" @page="onPage" :totalRecords="totalRecords" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander></Column>
<Column field="size" header="Size"></Column>
<Column field="type" header="Type"></Column>
</TreeTable>
添加 scrollable 属性以及数据视口的 scrollHeight,可以启用带有固定标题的垂直滚动。
<TreeTable :value="nodes" scrollable scrollHeight="270px" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>
灵活滚动功能使可滚动视口部分动态化,而不是固定值,以便它可以相对于表格的父大小增长或收缩。单击下面的按钮以显示一个可最大化的对话框,其中数据视口会根据大小变化自行调整。
<Button label="Show" icon="pi pi-external-link" @click="dialogVisible = true" />
<Dialog v-model:visible="dialogVisible" header="Flex Scroll" :style="{ width: '75vw' }" maximizable modal :contentStyle="{ height: '300px' }">
<TreeTable :value="nodes" :scrollable="true" scrollHeight="flex" tableStyle="min-width: 50rem">
<Column field="name" header="Name" :expander="true" style="min-width: 200px"></Column>
<Column field="size" header="Size" style="min-width: 200px"></Column>
<Column field="type" header="Type" style="min-width: 200px"></Column>
</TreeTable>
<template #footer>
<Button label="Ok" icon="pi pi-check" @click="dialogVisible = false" />
</template>
</Dialog>
当表格宽度超过父宽度时,会显示水平滚动条。
<TreeTable :value="nodes" scrollable scrollHeight="300px">
<Column field="name" header="Name" expander style="min-width: 250px"></Column>
<Column field="size" header="Size" style="min-width: 200px"></Column>
<Column field="type" header="Type 2" style="min-width: 200px"></Column>
<Column field="size" header="Size 2" style="min-width: 200px"></Column>
<Column field="type" header="Type 3" style="min-width: 200px"></Column>
<Column field="size" header="Size 3" style="min-width: 200px"></Column>
</TreeTable>
可以通过在列上启用 frozen 属性,在水平滚动期间固定列。该位置是通过可以是 left 或 right 的 alignFrozen 定义的。
<TreeTable :value="nodes" scrollable scrollHeight="300px">
<Column field="name" header="Name" expander frozen style="min-width: 250px" class="font-bold"></Column>
<Column field="size" header="Size" style="min-width: 200px"></Column>
<Column field="type" header="Type 2" style="min-width: 200px"></Column>
<Column field="size" header="Size 2" style="min-width: 200px"></Column>
<Column field="type" header="Type 3" style="min-width: 200px"></Column>
<Column field="size" header="Size 3" style="min-width: 200px"></Column>
</TreeTable>
启用 resizableColumns 后,可以通过拖放来调整列大小。默认调整大小模式是 fit,该模式不会更改表格的整体宽度。
<TreeTable :value="nodes" :resizableColumns="true" showGridlines tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander></Column>
<Column field="size" header="Size"></Column>
<Column field="type" header="Type"></Column>
</TreeTable>
将 columnResizeMode 设置为 expand 也会更改表格宽度。
<TreeTable :value="nodes" :resizableColumns="true" columnResizeMode="expand" showGridlines tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander></Column>
<Column field="size" header="Size"></Column>
<Column field="type" header="Type"></Column>
</TreeTable>
可以使用动态列来实现基于条件的列可见性,在此示例中,使用多选来管理可见的列。
<TreeTable :value="nodes" tableStyle="min-width: 50rem">
<template #header>
<div style="text-align:left">
<MultiSelect :modelValue="selectedColumns" @update:modelValue="onToggle" :options="columns" optionLabel="header" class="w-full sm:w-64" display="chip"/>
</div>
</template>
<Column field="name" header="Name" :expander="true"></Column>
<Column v-for="col of selectedColumns" :field="col.field" :header="col.header" :key="col.field"></Column>
</TreeTable>
树形表格使用 contextMenu 事件与上下文菜单进行独占集成,以在右键单击时打开菜单,以及使用 contextMenuSelection 属性和 row-contextmenu 事件来控制通过菜单进行选择。
<ContextMenu ref="cm" :model="menuModel" @hide="selectedNode = null" />
<TreeTable v-model:contextMenuSelection="selectedNode" :value="nodes" contextMenu @row-contextmenu="onRowContextMenu" tableStyle="min-width: 50rem">
<Column field="name" header="Name" expander style="width: 34%"></Column>
<Column field="size" header="Size" style="width: 33%"></Column>
<Column field="type" header="Type" style="width: 33%"></Column>
</TreeTable>
数据表格使用 treegrid 元素,可以使用 tableProps 选项扩展其属性。此属性允许将 aria 角色和属性(如 aria-label 和 aria-describedby)传递给阅读器定义表格。表格的默认角色是 table。标题、正文和页脚元素使用 rowgroup,行使用 row 角色,标题单元格使用 columnheader,正文单元格使用 cell 角色。可排序的标题利用 aria-sort 属性设置为 “ascending” 或 “descending”。
行元素管理状态的 aria-expanded,以及定义层次结构的 aria-posinset、aria-setsize 和 aria-level 属性。
启用选择后,行上的 aria-selected 设置为 true。在复选框模式下,树形表格组件使用隐藏的本机复选框元素。
可编辑的单元格使用自定义模板,因此如果需要,您需要手动管理 aria 角色和属性。
分页器是数据表格内部使用的独立组件,有关可访问性功能的更多信息,请参阅 分页器。
键 | 功能 |
---|---|
tab | 在标题之间移动。 |
enter | 对列进行排序。 |
space | 对列进行排序。 |
键 | 功能 |
---|---|
tab | 当焦点进入组件时,将焦点移动到第一个选定的节点;如果没有,则第一个元素接收焦点。如果焦点已经在组件内部,则将焦点移动到页面选项卡序列中的下一个可聚焦元素。 |
shift + tab | 当焦点进入组件时,如果存在上次选中的节点,则将焦点移动到该节点。如果没有,则第一个元素获得焦点。如果焦点已在组件内,则将焦点移动到页面制表符序列中的上一个可聚焦元素。 |
enter | 选择具有焦点的树节点。 |
space | 选择具有焦点的树节点。 |
向下箭头 | 将焦点移动到下一个树节点。 |
向上箭头 | 将焦点移动到上一个树节点。 |
向右箭头 | 如果节点已关闭,则打开节点;否则将焦点移动到第一个子节点。 |
向左箭头 | 如果节点已打开,则关闭节点;否则将焦点移动到父节点。 |
Home键 | 将焦点移动到第一个同级节点。 |
End键 | 将焦点移动到最后一个同级节点。 |