QTable 是一个允许您以表格方式显示数据的组件。它通常被称为数据表。它包含以下主要功能
- 过滤
- 排序
- 单行/多行选择,并带有自定义选择操作
- 分页(如果需要,包括服务器端分页)
- 网格模式(例如,您可以使用 QCards 以非表格方式显示数据)
- 通过作用域插槽完全自定义行和单元格
- 能够在数据行的顶部或底部添加额外的行
- 列选择器(通过在其中一个部分中描述的 QTableColumns 组件)
- 自定义顶部和/或底部表格控件
- 响应式设计
提示
如果您不需要 QTable 的分页、排序、过滤和所有其他功能,则可以考虑改用 QMarkupTable 组件。
定义列
让我们以配置 columns
属性为例。我们将告诉 QTable row-key
是 'name',它**必须**是唯一的。如果这是从数据库中获取的数据,我们可能会使用行的**id**。
columns: [ // array of Objects
// column Object definition
{
// unique id
// identifies column
// (used by pagination.sortBy, "body-cell-[name]" slot, ...)
name: 'desc',
// label for header
label: 'Dessert (100g serving)',
// row Object property to determine value for this column
field: 'name',
// OR field: row => row.some.nested.prop,
// (optional) if we use visible-columns, this col will always be visible
required: true,
// (optional) alignment
align: 'left',
// (optional) tell QTable you want this column sortable
sortable: true,
// (optional) compare function if you have
// some custom data or want a specific way to compare two rows
// --> note that rows with null/undefined as value will get auto sorted
// without calling this method (if you want to handle those as well, use "rawSort" instead)
sort: (a, b, rowA, rowB) => parseInt(a, 10) - parseInt(b, 10),
// function return value:
// * is less than 0 then sort a to an index lower than b, i.e. a comes first
// * is 0 then leave a and b unchanged with respect to each other, but sorted with respect to all different elements
// * is greater than 0 then sort b to an index lower than a, i.e. b comes first
// (optional) requires Quasar v2.13+
// compare function if you have
// some custom data or want a specific way to compare two rows
// --> note that there is an alternative "sort" method (above) if you don't
// want to handle (by yourself) rows with null/undefined as value
rawSort: (a, b, rowA, rowB) => parseInt(a, 10) - parseInt(b, 10),
// has the same return value as the alternative "sort" method above
// (optional) override 'column-sort-order' prop;
// sets column sort order: 'ad' (ascending-descending) or 'da' (descending-ascending)
sortOrder: 'ad', // or 'da'
// (optional) you can format the data with a function
format: (val, row) => `${val}%`,
// one more format example:
// format: val => val
// ? /* Unicode checkmark checked */ "\u2611"
// : /* Unicode checkmark unchecked */ "\u2610",
// body td:
style: 'width: 500px',
// or as Function --> style: row => ... (return String/Array/Object)
classes: 'my-special-class',
// or as Function --> classes: row => ... (return String)
// header th:
headerStyle: 'width: 500px',
headerClasses: 'my-special-class'
},
{ name: 'calories', label: 'Calories', field: 'calories', sortable: true },
{ name: 'fat', label: 'Fat (g)', field: 'fat', sortable: true },
{ name: 'carbs', label: 'Carbs (g)', field: 'carbs' },
{ name: 'protein', label: 'Protein (g)', field: 'protein' },
{ name: 'sodium', label: 'Sodium (mg)', field: 'sodium' },
{ name: 'calcium', label: 'Calcium (%)', field: 'calcium', sortable: true, sort: (a, b) => parseInt(a, 10) - parseInt(b, 10) },
{ name: 'iron', label: 'Iron (%)', field: 'iron', sortable: true, sort: (a, b) => parseInt(a, 10) - parseInt(b, 10) }
]
基本用法
提示
您可以将 dense
属性与 $q.screen
一起使用以创建响应式行为。例如::dense="$q.screen.lt.md"
。更多信息:屏幕插件。
省略列定义
您可以省略指定 columns
。QTable 将从数据第一行的属性推断列。请注意,标签将转换为大写,并且启用了排序
粘性头部/列
警告
粘性头部和列是通过使用 position: sticky
的 CSS 实现的。这并非所有浏览器都支持。在使用此技术之前,请查看 caniuse.com。
提示
请注意以下示例中“style”部分中的代码,尤其是在 position: sticky
附近。
分隔符
样式
虚拟滚动
请注意,启用虚拟滚动时,您需要指定 table-style
(具有最大高度)属性。在下面的示例中,我们还强制 QTable 同时显示所有行(请注意 pagination
和 rows-per-page-options
属性的使用)。
当滚动到达末尾时,您可以动态加载新行
您可以同时使用虚拟滚动和分页
下面的示例显示了如何将虚拟滚动与粘性头部一起使用。请注意 virtual-scroll-sticky-start
属性,它设置为头部高度。
有两个实用程序 CSS 类控制 VirtualScroll 大小计算
- 在由 VirtualScroll 渲染的元素上使用
q-virtual-scroll--with-prev
类,以指示该元素应与前一个元素分组(主要用例是为从同一数据行生成的多个表格行)。 - 在由 VirtualScroll 渲染的元素上使用
q-virtual-scroll--skip
类,以指示在大小计算中应忽略该元素的大小。
选择
警告
为了使选择正常工作,必须设置属性 row-key
。
可见列、自定义顶部、全屏
请注意,标记为 required
(在列定义中)的列无法切换,并且始终可见。
弹出式编辑
提示
下面是一个示例,用户可以在 QPopupEdit 组件的帮助下“就地”编辑。请注意,我们正在使用 body
作用域插槽。QPopupEdit 不适用于单元格作用域插槽。
使用输入进行编辑
网格样式
提示
您可以将 grid
属性与 $q.screen
一起使用以创建响应式行为。例如::grid="$q.screen.lt.md"
。更多信息:屏幕插件。
在下面的示例中,我们让 QTable 处理显示网格模式(不使用特定插槽)
但是,如果您想完全自定义内容,请查看下面的示例,其中
- 我们使用名为
item
的 Vue 作用域插槽来定义每个记录(相当于非网格模式下的行)的外观。这使您可以完全自由。 - 我们正在使用多选。
扩展行
警告
如果您从数据中的某一行生成多个 QTr,则在 QTr 上添加唯一的(不同的)key
。
也可以使用外部扩展模型
如果您正在将虚拟滚动与 QTable 一起使用,则应该知道有两个实用程序 CSS 类控制 VirtualScroll 大小计算
- 在由 VirtualScroll 渲染的元素上使用
q-virtual-scroll--with-prev
类,以指示该元素应与前一个元素分组(主要用例是为从同一数据行生成的多个表格行)。 - 在由 VirtualScroll 渲染的元素上使用
q-virtual-scroll--skip
类,以指示在大小计算中应忽略该元素的大小。
之前/之后插槽
分页
提示
当 pagination
拥有名为 rowsNumber
的属性时,这意味着您将配置 Table 进行**服务器端**分页(以及排序和过滤)。请参阅“服务器端分页、过滤和排序”部分。
以下是处理分页(以及排序和每页行数)的两个示例。
第一个示例重点介绍如何配置初始分页。
第二个示例使用“v-model:pagination”指令,因为我们希望随时访问其当前值。以下技术的用例可以是从 QTable 外部控制分页。
分页插槽
出于学习目的,我们将使用默认控件自定义分页控件,以帮助您开始使用自己的控件。
加载状态
自定义顶部
主体插槽
以下示例演示了如何使用插槽自定义整个行。
下面,我们使用一个插槽,该插槽应用于每个主体单元格。
我们还可以仅自定义一个特定的列。此插槽的语法为 body-cell-[name]
,其中 [name]
应替换为用作行键的每一行的属性。
头部插槽
以下示例演示了如何使用插槽自定义整个头部行。
下面,我们使用一个插槽,该插槽应用于每个头部单元格。
我们还可以仅自定义一个特定的头部单元格。此插槽的语法为 header-cell-[name]
,其中 [name]
应替换为用作行键的每一行的属性。
无数据
还有一个“no-data”作用域插槽(见下文),您也可以使用它来自定义筛选器未返回任何结果或表格没有数据显示时的消息。也可以在“搜索”输入框中输入一些内容。
处理底部层
有一些属性可用于隐藏底部层或其特定部分。您可以在下面进行尝试。
自定义排序
响应式表格
为了创建响应式表格,我们有两个工具可以使用:dense
和 grid
属性。我们可以将它们与 $q.screen
连接起来。更多信息:屏幕插件。
下面的第一个示例使用 $q.screen.lt.md
(用于启用密集模式),第二个示例使用 $q.screen.xs
来启用网格模式,因此请调整浏览器宽度以查看它们的效果。
服务器端分页、过滤和排序
当您的数据库包含大量 Table 行时,出于多种原因(内存、UI 渲染性能等),显然不可能全部加载它们。相反,您可以只加载一个 Table 页面。每当用户想要导航到另一个 Table 页面,或想要按列排序或想要筛选 Table 时,都会向**服务器**发送一个**请求**以获取部分分页数据。
启用此行为的第一步是指定
pagination
属性,该属性**必须**包含rowsNumber
。QTable 需要知道可用行的总数才能正确渲染分页链接。如果筛选导致rowsNumber
发生变化,则必须对其进行动态修改。第二步是在 QTable 上监听
@request
事件。当需要从**服务器**获取数据时(因为页码、排序或筛选发生了更改),将触发此事件。最好也指定
loading
属性,以通知用户后台进程正在进行中。
提示
在下面的示例中,已采取措施模拟对服务器的 ajax 调用。虽然概念相似,但如果您使用此代码,则需要进行相应的更改以连接到您自己的数据源。
导出数据
以下是一个简单的 csv 编码示例,然后使用 exportFile Quasar 实用程序导出表格数据。浏览器应该会触发文件下载。对于更专业的编码方法,我们建议使用 csv-parse 和 csv-stringify 包。
提示
如果您想导出用户筛选+排序的数据,也可以使用 QTable 的内部计算属性 filteredSortedRows
。
键盘导航
以下是在表格中使用选中行进行键盘导航的示例。使用 ArrowUp
、ArrowDown
、PageUp
、PageDown
、Home
和 End
键进行导航。