为什么捐赠
API 浏览器
联系站长
表格

QTable 是一个允许您以表格方式显示数据的组件。它通常被称为数据表。它包含以下主要功能:

  • 筛选
  • 排序
  • 单行/多行选择,支持自定义选择操作
  • 分页(如果需要,包括服务器端分页)
  • 网格模式(您可以使用例如 QCards 以非表格方式显示数据)
  • 通过作用域插槽完全自定义行和单元格
  • 能够在数据行的顶部或底部添加额外的行
  • 列选择器(通过其中一节描述的 QTableColumns 组件)
  • 自定义表格顶部和/或底部控件
  • 响应式设计

TIP

如果您不需要分页、排序、筛选和 QTable 的所有其他功能,那么您可能想要查看 QMarkupTable 组件。

正在加载 QTable API...
正在加载 QTh API...
正在加载 QTr API...
正在加载 QTd API...

定义列

让我们以配置 columns 属性为例。我们将告诉 QTable row-key 是 ‘name’,它必须是唯一的。如果这是从数据库获取的数据,我们可能会使用行的 id

columns: [
  // 对象数组
  // 列对象定义
  {
    // 唯一 id
    // 标识列
    // (用于 pagination.sortBy, "body-cell-[name]" 插槽, ...)
    name: "desc",

    // 头部标签
    label: "Dessert (100g serving)",

    // 行对象属性,用于确定此列的值
    field: "name",
    // 或 field: row => row.some.nested.prop,

    // (可选) 如果我们使用 visible-columns,此列将始终可见
    required: true,

    // (可选) 对齐方式
    align: "left",

    // (可选) 告诉 QTable 您希望此列可排序
    sortable: true,

    // (可选) 如果您有自定义数据或想要特定方式比较两行,可以使用比较函数
    // --> 注意,值为 null/undefined 的行将自动排序
    // 而不调用此方法(如果您也想处理这些行,请使用 "rawSort")
    sort: (a, b, rowA, rowB) => parseInt(a, 10) - parseInt(b, 10),
    // 函数返回值:
    //   * 小于 0 则将 a 排序到比 b 更低的索引,即 a 在前
    //   * 等于 0 则保持 a 和 b 相对于彼此不变,但相对于所有不同元素排序
    //   * 大于 0 则将 b 排序到比 a 更低的索引,即 b 在前

    // (可选) 需要 Quasar v2.13+
    // 如果您有自定义数据或想要特定方式比较两行,可以使用比较函数
    // --> 注意,如果您不想(自己)处理值为 null/undefined 的行,
    // 有一个替代的 "sort" 方法(上面)
    rawSort: (a, b, rowA, rowB) => parseInt(a, 10) - parseInt(b, 10),
    // 与上面的替代 "sort" 方法具有相同的返回值

    // (可选) 覆盖 'column-sort-order' 属性;
    // 设置列排序顺序:'ad'(升序-降序)或 'da'(降序-升序)
    sortOrder: "ad", // 或 'da'

    // (可选) 您可以使用函数格式化数据
    format: (val, row) => `${val}%`,
    // 另一个格式示例:
    // format: val => val
    //   ? /* Unicode 勾选标记已选中 */ "\u2611"
    //   : /* Unicode 勾选标记未选中 */ "\u2610",

    // body td:
    style: "width: 500px",
    // 或作为函数 --> style: row => ... (返回 String/Array/Object)
    classes: "my-special-class",
    // 或作为函数 --> classes: row => ... (返回 String)

    // header th:
    headerStyle: "width: 500px",
    // 或作为函数 --> headerStyle: () => ... (返回 String/Array/Object)
    headerClasses: "my-special-class",
    // 或作为函数 --> headerClasses: () => ... (返回 String)
  },
  { 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),
  },
];

用法

TIP

QTable 的第一个示例是使用 Vue 的 <template> 标签,但您也可以使用渲染函数(h)或 JSX。

WARNING

不要使用 QTable 来显示大量数据,因为浏览器会变慢或崩溃。在这种情况下,您可能需要考虑使用 无限滚动分页 组件。

基础

基础



黑色模式



紧凑模式



TIP

您可以将 dense 属性与 $q.screen 搭配使用来实现响应式的效果。例如::dense="$q.screen.lt.md",更多信息请参考:Screen Plugin

省略列定义

您可以省略定义列 columns,QTable 会根据数据中的第一列进行推断。需要注意的是,标题会自动转为大写,并且排序会自动开启。

从数据中推断列



固定表头/列

WARNING

请注意,固定表头或行是通过 CSS 中的 position: sticky 属性实现的,并不是所有的浏览器都支持它。使用前,请检查 caniuse.com

TIP

固定表头或列都是由 css 实现的,所以在下面的几个示例中要注意 style 部分的代码,尤其是 position: sticky

固定表头



固定第一列



固定最后一列



固定表头和列



固定表头和最后一列



分割线

分隔符



样式

自定义列



自定义颜色



无表头/表尾



虚拟滚动

当使用虚拟滚动时,您需要使用 table-style 属性声明一个最大高度。在下面的示例中,我们还强制一次性显示了所有的列(注意 paginationrows-per-page-options)。

基础虚拟滚动



您可以在滚动到底部时动态加载新数据:

动态加载虚拟滚动



您可以同时使用虚拟滚动和分页:

虚拟滚动和分页



下面的示例展示了如何将虚拟滚动与固定表头同时使用,请注意其中 virtual-scroll-sticky-start 属性被设置为了表头的高度。

带固定表头的虚拟滚动



这里有两个工具 CSS 类名可以控制虚滚动的大小计算:

  • 使用 q-virtual-scroll--with-prev 类可以使被虚拟滚动渲染的元素与上一个元素一起分组(主要用于从同一行数据生成的多个表行)。
  • 使用 q-virtual-scroll--skip 类可以使被虚拟滚动渲染的元素在计算大小时忽略此元素的大小。
一行数据对应多个表格行的虚拟滚动



选择

警告

为了使选中功能生效,必须设置 row-key 属性。

单选



多选



选择单元格插槽



带范围选择的选择单元格插槽



自定义多选



可见列,自定义头部,全屏

请注意在列定义中被标记了 required 的列无法被隐藏,始终可见。

可见列、自定义顶部和全屏



可见列



弹出编辑

TIP

下面的示例中,我们利用 QPopupEdit 组件实现了就地编辑数据的功能。请注意,我们使用的是 body 类型的插槽,如果使用单元格类型的插槽,QPopupEdit 无法生效。

弹出式编辑



输入框编辑

输入框编辑



网格样式

TIP

您可以将 grid 属性与 $q.screen 搭配使用以实现响应式的效果。例如::grid="$q.screen.lt.md". 更多信息请参考: 屏幕插件

下面的示例中,我们让 QTable 以网格模式展示(不使用特殊的插槽):

网格样式



带表头的网格



彩色网格样式



瀑布流式网格



然而,如果您想完全自定义内容,请看下面的示例,其中:

  • 我们使用一个 Vue 作用域范围的插槽,叫做 item 来定义每个记录应该如何展示(相当于非网格模式下的行),这样您就可以自由发挥了。
  • 我们开启多选
带插槽的网格样式



展开行

WARNING

如果您为一行数据生成了多个 QTr,请为每个 QTr 设置一个唯一的 key

内部展开模式



还可以采用外部扩张模式:

外部展开模式



如果您在 QTable 中使用虚拟滚动功能,您应该知道,有两个工具 CSS 类名可以控制虚滚动的大小计算:

  • 使用 q-virtual-scroll--with-prev 类可以使被虚拟滚动渲染的元素与上一个元素一起分组(主要用于从同一行数据生成的多个表行)。
  • 使用 q-virtual-scroll--skip 类可以使被虚拟滚动渲染的元素在计算大小时忽略此元素的大小。
带展开模式的虚拟滚动



前/后插槽

前/后插槽(表头/表尾)



分页

TIP

如果 pagination 声明了一个 rowsNumber 属性,那么就代表您为 Table 配置了服务端分页(& 排序 & 筛选)。请参考 服务端分页,排序和筛选 部分。

下面是两个处理分页(以及每页的排序和行数)的示例。

第一个示例强调如何配置基础分页功能:

初始分页



第二个示例使用 “v-model:pagination” 指令,因为我们希望随时访问它的当前值。以下技术的一个用例是从 QTable 外部控制分页

同步分页



分页插槽

出于学习目的,我们将使用一些基础的控件来实现自定义分页功能,以帮助您开始实现自己的分页控件。

分页插槽



加载状态

默认加载



自定义加载状态



自定义头部

带添加/删除行的自定义顶部



Body 插槽

下面的示例显示了如何使用插槽自定义整个行:

Body 插槽



下面我们使用一个会被应用到每个单元格的插槽:

Body-cell 插槽



我们也可以指定自定义某些特殊的列。这种插槽的写法是 body-cell-[name],其中 [name] 应该被替换成行中用作 row-key 的属性。

Body-cell-[name] 插槽



Header 插槽

下面的示例显示了如何使用槽自定义整个标题行

Header 插槽



下面我们使用一个会被应用于每个表头单元格的插槽:

Header-cell 插槽



我们也可以指定自定义某些特殊的表头单元格。这种插槽的写法是 header-cell-[name],其中 [name] 应该被替换成行中用作 row-key 的属性。

Header-cell-[name] 插槽



空数据

无数据标签



当表格没有数据可以展示时,您也可以使用空数据插槽 (“no-data”) 来自定义要展示的消息。也可以在 “Search” 输入框中输入一些数据。

无数据插槽



处理底层

有一些属性可以用于隐藏底部区域的一些部分,下面有一些示例:

隐藏底部层



自定义排序

自定义排序



响应式表格

为了实现响应式表格,我们有两个工具可以使用:densegrid 属性。我们还可以将其与 $q.screen 搭配使用,更多信息请参考:屏幕插件

下面的第一个示例使用了 $q.screen.lt.md 来开启紧凑模式,第二个示例使用了 $q.screen.xs 来开启网格模式,所以您需要调整浏览器的窗口大小来查看它们的变化。

使用 dense 属性



使用 grid 属性



服务端分页,排序和筛选

当您的数据库中拥有大量的数据时,出于内存,UI 渲染性能等原因,很明显不能一次性全部加载它们。您可以一次只加载表格的一页数据,当用户想要访问下一页数据,或者想要重新排序/筛选时,再去服务端重新请求对应的数据。

  1. 要开启这个行为的第一步是声明 pagination 属性,并且其中必须包括 rowsNumber 字段。QTable 需要知道可用的行总数,以便正确渲染分页控件。如果筛选导致 rowsNumber 更改,则必须动态修改它。

  2. 第二步是监听 QTable 的 @request 事件。如果因为页码,筛选或者排序的改变需要重新去服务端重新请求数据时,这个事件会被触发。

  3. 最好声明 loading 属性来告知用户,后台正在请求数据。

TIP

在下面的示例中,模拟了使用 ajax 对服务器进行请求的步骤。虽然概念相似,但如果您要使用此代码,还需要进行适当的更改以连接到您自己的数据源。

与服务器同步



导出数据

下面是一个简单的 csv 编码示例,然后使用 Quasar 提供的 exportFile 工具函数导出表格数据,浏览器应该会触发一个文件下载。对于更专业的编码方法,我们建议使用 csv-parsecsv-stringify 包。

提示

如果要导出用户筛选 + 排序的数据,还可以使用 QTable 内部的 filteredSortedRows 计算属性。

导出为 CSV



键盘导航

下面是一个使用键盘在表格所选行中导航的示例。使用 ArrowUpArrowDownPageUpPageDownHomeEnd 键进行导航。

键盘导航