QTable 是一个允许你以表格方式显示数据的组件。它通常被称为数据表。它包含以下主要功能:
¥QTable is a component that allows you to display data in a tabular manner. It’s generally called a datatable. It packs the following main features:
过滤
¥Filtering
排序
¥Sorting
使用自定义选择操作进行单行/多行选择
¥Single / Multiple rows selection with custom selection actions
分页(如果需要,包括服务器端)
¥Pagination (including server-side if required)
网格模式(例如,你可以使用 QCards 以非表格方式显示数据)
¥Grid mode (you can use for example QCards to display data in a non-tabular manner)
通过作用域插槽完全自定义行和单元格
¥Total customization of rows and cells through scoped slots
能够在数据行的顶部或底部添加额外行
¥Ability to add additional row(s) at top or bottom of data rows
列选择器(通过其中一节中描述的 QTableColumns 组件)
¥Column picker (through QTableColumns component described in one of the sections)
自定义顶部和/或底部表格控件
¥Custom top and/or bottom Table controls
响应式设计
¥Responsive design
提示
如果你不需要 QTable 的分页、排序、过滤和所有其他功能,那么你可能需要查看 QMarkupTable 组件。
¥If you don’t need pagination, sorting, filtering, and all other features of QTable, then you may want to check out QMarkupTable component instead.
定义列(Defining the columns)
¥Defining the columns
让我们以配置 columns
属性为例。我们将告诉 QTable,row-key
是“名称”,它必须是唯一的。如果这是从数据库获取的数据,我们可能会使用行 ID。
¥Let’s take an example of configuring the columns
property. We are going to tell QTable that row-key
is ‘name’, which must be unique. If this was data fetched from a database we would likely use the row 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) }
]
基本用法(Basic usage)
¥Basic usage
提示
你可以将 dense
属性与 $q.screen
属性一起使用来创建响应式行为。示例::dense="$q.screen.lt.md"
。更多信息:屏幕插件。
¥You can use the dense
prop along with $q.screen
to create a responsive behavior. Example: :dense="$q.screen.lt.md"
. More info: Screen Plugin.
省略列定义(Omitting columns definition)
¥Omitting columns definition
你可以省略指定 columns
。QTable 会根据数据第一行的属性推断列。请注意,标签必须大写,并且已启用排序:
¥You can omit specifying the columns
. QTable will infer the columns from the properties of the first row of the data. Note that labels are uppercased and sorting is enabled:
固定标题/列(Sticky header/column)
¥Sticky header/column
警告
固定标题和列是通过 CSS 和 position: sticky
实现的。并非所有浏览器都支持此功能。使用此技术之前,请先检查 caniuse.com。
¥Sticky headers and columns are achieved through CSS with position: sticky
. This is NOT supported on all browsers. Check caniuse.com before using this technique.
提示
请注意以下示例中 “style” 部分的代码,尤其是 position: sticky
部分。
¥Pay attention to the code in the “style” section in the following examples, especially around position: sticky
.
分隔符(Separators)
¥Separators
样式(Styling)
¥Styling
提示
要查看所有样式组件属性,请查看页面顶部的 API 卡片。
¥For all the styling component properties, please check the API card at the top of the page.
虚拟滚动(Virtual scrolling)
¥Virtual scrolling
请注意,启用虚拟滚动时,你需要指定 table-style
(带有 max-height)属性。在下面的示例中,我们还强制 QTable 一次显示所有行(注意 pagination
和 rows-per-page-options
属性的使用)。
¥Notice that when enabling virtual scroll you will need to specify the table-style
(with a max-height) prop. In the example below, we are also forcing QTable to display all rows at once (note the use of pagination
and rows-per-page-options
props).
你可以在滚动到末尾时动态加载新行:
¥You can dynamically load new rows when scroll reaches the end:
你可以同时使用虚拟滚动和分页:
¥You can have both virtual scroll and pagination:
以下示例展示了如何将虚拟滚动与粘性标题一起使用。注意 virtual-scroll-sticky-start
属性,它被设置为标题高度。
¥The example below shows how virtual scroll can be used along with a sticky header. Notice the virtual-scroll-sticky-start
prop which is set to the header height.
有两个实用 CSS 类用于控制 VirtualScroll 大小的计算:
¥There are 2 utility CSS classes that control VirtualScroll size calculation:
在 VirtualScroll 渲染的元素上使用
q-virtual-scroll--with-prev
类,以指示该元素应与前一个元素分组(主要用例是从同一行数据生成的多个表格行)。¥Use
q-virtual-scroll--with-prev
class on an element rendered by the VirtualScroll to indicate that the element should be grouped with the previous one (main use case is for multiple table rows generated from the same row of data).在 VirtualScroll 渲染的元素上使用
q-virtual-scroll--skip
类,以指示在大小计算中应忽略该元素的大小。¥Use
q-virtual-scroll--skip
class on an element rendered by the VirtualScroll to indicate that the element’s size should be ignored in size calculations.
选择(Selection)
¥Selection
警告
必须设置属性 row-key
才能使选择功能正常工作。
¥The property row-key
must be set in order for selection to work properly.
可见列、自定义顶部、全屏(Visible columns, custom top, fullscreen)
¥Visible columns, custom top, fullscreen
请注意,标记为 required
的列(在列定义中)无法切换,并且始终可见。
¥Please note that columns marked as required
(in the column definition) cannot be toggled and are always visible.
弹出窗口编辑(Popup editing)
¥Popup editing
提示
以下是用户能够借助 QPopupEdit 组件进行“就地”编辑的示例。请注意,我们正在使用 body
作用域插槽。QPopupEdit 不支持单元格范围的插槽。
¥Below is an example with the user being able to edit “in place” with the help of QPopupEdit component. Please note that we are using the body
scoped slot. QPopupEdit won’t work with cell scoped slots.
使用输入框编辑(Editing with an input)
¥Editing with an input
网格样式(Grid style)
¥Grid style
提示
你可以将 grid
属性与 $q.screen
属性一起使用来创建响应式行为。示例::grid="$q.screen.lt.md"
。更多信息:屏幕插件。
¥You can use the grid
prop along with $q.screen
to create a responsive behavior. Example: :grid="$q.screen.lt.md"
. More info: Screen Plugin.
在下面的示例中,我们让 QTable 处理网格模式的显示(不使用特定的插槽):
¥In the example below, we let QTable deal with displaying the grid mode (not using the specific slot):
但是,如果你想完全自定义内容,请查看以下示例,其中:
¥However, if you want to fully customize the content, check the example below, where:
我们使用一个名为
item
的 Vue 作用域插槽来定义每条记录(相当于非网格模式下的一行)的外观。这为你提供了完全的自由。¥We are using a Vue scoped slot called
item
to define how each record (the equivalent of a row in non-grid mode) should look. This allows you total freedom.我们使用多选功能。
¥We are using multiple selection.
扩展行(Expanding rows)
¥Expanding rows
警告
如果你从数据中的一行生成多个 QTr,请在 QTr 上添加唯一的(不同的)key
。
¥Add unique (distinct) key
on QTr if you generate more than one QTr from a row in data.
也可以使用外部扩展模型:
¥An external expansion model can also be used:
如果你在 QTable 中使用虚拟滚动,你应该知道有两个实用 CSS 类可以控制 VirtualScroll 的大小计算:
¥If you are using virtual scroll with QTable, you should know that there are 2 utility CSS classes that control VirtualScroll size calculation:
在 VirtualScroll 渲染的元素上使用
q-virtual-scroll--with-prev
类,以指示该元素应与前一个元素分组(主要用例是从同一行数据生成的多个表格行)。¥Use
q-virtual-scroll--with-prev
class on an element rendered by the VirtualScroll to indicate that the element should be grouped with the previous one (main use case is for multiple table rows generated from the same row of data).在 VirtualScroll 渲染的元素上使用
q-virtual-scroll--skip
类,以指示在大小计算中应忽略该元素的大小。¥Use
q-virtual-scroll--skip
class on an element rendered by the VirtualScroll to indicate that the element’s size should be ignored in size calculations.
升级前/升级后插槽(Before/after slots)
¥Before/after slots
分页(Pagination)
¥Pagination
提示
当 pagination
具有名为 rowsNumber
的属性时,这意味着你将配置 Table 以进行服务器端分页(以及排序和过滤)。参见 “服务器端分页、过滤和排序” 部分。
¥When pagination
has a property named rowsNumber
, then this means that you’ll be configuring Table for server-side pagination (& sorting & filtering). See “Server side pagination, filter and sorting” section.
以下是两个处理分页(以及排序和每页行数)的示例。
¥Below are two examples of handling the pagination (and sorting and rows per page).
第一个例子重点介绍了如何配置初始分页:
¥The first example highlights how to configure the initial pagination:
第二个示例使用 “v-model:pagination” 指令,因为我们希望随时访问其当前值。以下技术的一个用例是从 QTable 外部控制分页。
¥The second example uses the “v-model:pagination” directive because we want to access its current value at any time. A use-case for the technique below can be to control the pagination from outside of QTable.
分页槽(Pagination slot)
¥Pagination slot
出于学习目的,我们将使用默认控件自定义分页控件,以帮助你开始使用自己的控件。
¥For learning purposes, we will customize the pagination controls with the default controls in order to help you get started with your own.
加载状态(Loading state)
¥Loading state
自定义顶部(Custom top)
¥Custom top
Body 插槽(Body slots)
¥Body slots
以下示例展示了如何使用插槽自定义整行:
¥The example below shows how you can use a slot to customize the entire row:
下面,我们使用一个应用于每个 body 单元格的 slot:
¥Below, we use a slot which gets applied to each body cell:
我们也可以只自定义一个特定的列。此插槽的语法为 body-cell-[name]
,其中 [name]
应替换为用作行键的每一行的属性。
¥We can also customize only one particular column only. The syntax for this slot is body-cell-[name]
, where [name]
should be replaced by the property of each row which is used as the row-key.
标题栏位(Header slots)
¥Header slots
以下示例展示了如何使用插槽自定义整个标题行:
¥The example below shows how you can use a slot to customize the entire header row:
下面,我们使用一个应用于每个 header 单元格的 slot:
¥Below, we use a slot which gets applied to each header cell:
我们也可以只自定义一个特定的标题单元格。此插槽的语法为 header-cell-[name]
,其中 [name]
应替换为用作行键的每一行的属性。
¥We can also customize only one particular header cell only. The syntax for this slot is header-cell-[name]
, where [name]
should be replaced by the property of each row which is used as the row-key.
无数据(No data)
¥No data
还有一个 “no-data” 作用域插槽(见下文),当过滤器未返回任何结果或表格中没有数据可显示时,你还可以自定义两者的消息。另请在 “搜索” 输入框中输入一些内容。
¥There is also a “no-data” scoped slot (see below) that you can also to customize the messages for both when a filter doesn’t returns any results or the table has no data to display. Also type something into the “Search” input.
处理底层(Handling bottom layer)
¥Handling bottom layer
有一些属性可用于隐藏底层或其特定部分。你可以在下面试用:
¥There are a few properties that you can use to hide the bottom layer or specific parts of it. You can play with it below:
自定义排序(Custom sorting)
¥Custom sorting
响应式表格(Responsive tables)
¥Responsive tables
为了创建响应式表格,我们有两个工具可供使用:dense
和 grid
属性。我们可以将它们与 $q.screen
连接。更多信息:屏幕插件。
¥In order to create responsive tables, we have two tools at our disposal: dense
and grid
properties. We can connect these with $q.screen
. More info: Screen Plugin.
下面的第一个示例使用 $q.screen.lt.md
(用于启用密集模式),第二个示例使用 $q.screen.xs
启用网格模式,因此请尝试调整浏览器宽度来查看它们的实际效果。
¥First example below uses $q.screen.lt.md
(for enabling dense mode) and the second examples uses $q.screen.xs
to enable grid mode, so play with browser width to see them in action.
服务器端分页、过滤和排序(Server side pagination, filter and sorting)
¥Server side pagination, filter and sorting
当你的数据库包含大量表行时,由于多种原因(内存、UI 渲染性能等),加载所有行显然是不可行的。相反,你可以只加载一个表格页面。每当用户想要导航到另一个表格页面,或者想要按列排序或想要过滤表格时,都会向服务器发送请求以获取部分分页的数据。
¥When your database contains a big number of rows for a Table, obviously it’s not feasible to load them all for multiple reasons (memory, UI rendering performance, …). Instead, you can load only a Table page. Whenever the user wants to navigate to another Table page, or wants to sort by a column or wants to filter the Table, a request is sent to the server to fetch the partially paged data.
启用此行为的第一步是指定
pagination
属性,该属性必须包含rowsNumber
。QTable 需要知道可用的总行数才能正确渲染分页链接。如果过滤导致rowsNumber
发生变化,则必须动态修改。¥First step to enable this behavior is to specify
pagination
prop, which MUST containrowsNumber
. QTable needs to know the total number of rows available in order to correctly render the pagination links. Should filtering cause therowsNumber
to change then it must be modified dynamically.第二步是监听 QTable 上的
@request
事件。当页码、排序或筛选条件发生变化,需要从服务器获取数据时,会触发此事件。¥Second step is to listen for
@request
event on QTable. This event is triggered when data needs to be fetched from the server because either page number or sorting or filtering changed.最好也指定
loading
属性,以便通知用户后台进程正在进行中。¥It’s best that you also specify the
loading
prop in order to notify the user that a background process is in progress.
提示
在以下示例中,已采取步骤模拟对服务器的 Ajax 调用。虽然概念相似,但如果你使用此代码,则需要进行适当的更改以连接到你自己的数据源。
¥In the example below, steps have been taken to emulate an ajax call to a server. While the concepts are similar, if you use this code you will need to make the appropriate changes to connect to your own data source.
导出数据(Exporting data)
¥Exporting data
下面是一个使用 exportFile Quasar 实用程序进行简单 csv 编码然后导出表格数据的示例。浏览器应该会触发文件下载。为了获得更专业的编码方法,我们建议使用 csv-parse 和 csv-stringify 包。
¥Below is an example of a naive csv encoding and then exporting table data by using the exportFile Quasar util. The browser should trigger a file download. For a more professional approach in regards to encoding we do recommend using csv-parse and csv-stringify packages.
提示
如果你想导出用户过滤和排序后的数据,还可以使用 QTable 的 filteredSortedRows
内部计算属性。
¥You could also make use of the filteredSortedRows
internal computed property of QTable should you want to export the user filtered + sorted data.
键盘导航(Keyboard navigation)
¥Keyboard navigation
以下是使用选定行在表格中进行键盘导航的示例。使用 ArrowUp
、ArrowDown
、PageUp
、PageDown
、Home
和 End
键进行导航。
¥Below is an example of keyboard navigation in the table using selected row. Use ArrowUp
, ArrowDown
, PageUp
, PageDown
, Home
and End
keys to navigate.