☰
Flowbite Datatables 插件实战指南:基于 Tailwind CSS 构建可搜索、排序、筛选、分页与导出的数据表格
2026/9/25 5:51:51 网站建设 项目流程
  • UI组件
  • 前端

【免费下载链接】flowbite

Open-source UI component library and front-end development framework based on Tailwind CSS

项目地址:https://gitcode.com/gh_mirrors/fl/flowbite
点击查看免费下载

本指南以 Flowbite 官方文档中的 Datatables 插件页面(content/plugins/datatables.md)为蓝本,系统讲解如何在基于 Tailwind CSS 的项目中集成simple-datatables库,实现面向数千条数据的搜索、排序、逐列筛选、分页、行选中与 CSV/TXT/JSON/SQL 导出能力。读完本文,你将掌握从 NPM/CDN 安装、初始化DataTable实例,到逐一配置各项行为选项与调用实例方法的完整实战链路,并能直接复用文中给出的可运行代码。

Flowbite 的 Datatables 组件示例基于开源库 simple-datatables 中。

快速开始:安装依赖

在继续之前,请确保你的项目中已具备以下三样东西:Tailwind CSS、Flowbite、Simple Datatables。

  1. 安装 Tailwind CSS 并完成 Flowbite 接入:请先按照快速上手指南安装 Tailwind CSS 与 Flowbite,并在 CSS 中通过@plugin "flowbite/plugin"引入官方插件。flowbite/plugin默认会启用datatables = true,从而注入.datatable-wrapper、.datatable-container、.datatable-pagination等一系列专属样式类(详见 plugin.js 中的addComponents定义,包括表格边框、圆角、搜索框、下拉选择器与分页按钮的完整样式)。

  2. 通过 NPM 安装simple-datatables库:

npm install simple-datatables --save
  1. 或者使用 CDN 方式引入:
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@9.0.3"></script>

说明:仓库文档站点的示例短代码(layouts/_shortcodes/example.html)在渲染 datatables 示例时正是通过 CDN 加载simple-datatables@9.0.4,随后在window.onload中执行示例自身的初始化脚本,这与你手动引入的流程完全一致。

完成上述安装后,就可以从 Flowbite 文档中复制 Datatables 组件了。需要注意:除了 HTML 标记外,务必同时复制用于初始化组件的 JavaScript 代码,二者缺一不可。

默认数据表格:开箱即用的排序与分页

下面的示例演示如何用最少的配置展示带默认排序和分页功能的表格数据。HTML 部分就是一个带id="default-table"的普通<table>,列头内通过data-type/data-format属性声明日期列的解析规则;JavaScript 部分则创建DataTable实例并关闭搜索与每页条数选择器:

if (document.getElementById("default-table") && typeof simpleDatatables.DataTable !== 'undefined') { const dataTable = new simpleDatatables.DataTable("#default-table", { searchable: false, perPageSelect: false }); }
<table id="default-table"> <thead> <tr> <th> <span class="flex items-center"> Name <!-- 上下箭头 SVG(w-4 h-4 ms-1,可省略) --> </span> </th> <th>if (document.getElementById("search-table") && typeof simpleDatatables.DataTable !== 'undefined') { const dataTable = new simpleDatatables.DataTable("#search-table", { searchable: true, sortable: false }); }
<table id="search-table"> <thead> <tr> <th><span class="flex items-center">Company Name</span></th> <th><span class="flex items-center">Ticker</span></th> <th><span class="flex items-center">Stock Price</span></th> <th><span class="flex items-center">Market Capitalization</span></th> </tr> </thead> <tbody> <tr> <td class="font-medium text-heading whitespace-nowrap">Apple Inc.</td> <td>AAPL</td> <td>$192.58</td> <td>$3.04T</td> </tr> <tr> <td class="font-medium text-heading whitespace-nowrap">Microsoft Corporation</td> <td>MSFT</td> <td>$340.54</td> <td>$2.56T</td> </tr> <!-- 其余约 30 行数据见 content/plugins/datatables.md --> </tbody> </table>

逐列过滤:在表头为每一列注入搜索框

当数据列较多、字段含义各异时,"按列筛选"比全局搜索更高效。要实现这一点,需要把 JavaScript 标签页中的自定义代码与表格 HTML 结构一起复制:通过tableRender回调在每次渲染(打印预览除外)时为每个表头列动态插入一个<input type="search">,并用data-columns属性声明该输入框作用的列索引:

if (document.getElementById("filter-table") && typeof simpleDatatables.DataTable !== 'undefined') { const dataTable = new simpleDatatables.DataTable("#filter-table", { tableRender: (_data, table, type) => { if (type === "print") { return table } const tHead = table.childNodes[0] const filterHeaders = { nodeName: "TR", attributes: { class: "search-filtering-row" }, childNodes: tHead.childNodes[0].childNodes.map( (_th, index) => ({nodeName: "TH", childNodes: [ { nodeName: "INPUT", attributes: { class: "datatable-input", type: "search", "data-columns": "[" + index + "]" } } ]}) ) } tHead.childNodes.push(filterHeaders) return table } }); }
<table id="filter-table"> <thead> <tr> <th><span class="flex items-center">Name</span></th> <th><span class="flex items-center">Category</span></th> <th><span class="flex items-center">Brand</span></th> <th><span class="flex items-center">Price</span></th> <th><span class="flex items-center">Stock</span></th> <th><span class="flex items-center">Total Sales</span></th> <th><span class="flex items-center">Status</span></th> </tr> </thead> <tbody> <tr> <td class="font-medium text-heading whitespace-nowrap">Apple iMac</td> <td>Computers</td> <td>Apple</td> <td>$1,299</td> <td>50</td> <td>200</td> <td>In Stock</td> </tr> <tr> <td class="font-medium text-heading whitespace-nowrap">Apple iPhone</td> <td>Mobile Phones</td> <td>Apple</td> <td>$999</td> <td>120</td> <td>300</td> <td>In Stock</td> </tr> <!-- 其余产品行见 content/plugins/datatables.md --> </tbody> </table>

实现原理:tableRender是 simple-datatables 提供的渲染钩子,这里借助它向<thead>追加一行 class 为search-filtering-row的TR,每列一个搜索输入框。Flowbite 插件在 plugin.js 中针对该行做了专门的样式适配(.datatable-wrapper .datatable-container thead tr.search-filtering-row th { padding-top: 0 }),使筛选行紧贴列头;同时输入框复用.datatable-input类(plugin.js),在暗色模式下同样生效。

数据排序:点击列头升降序

把sortable设为true,所有数据行即可通过点击表头按列升序/降序排列;设为false则关闭该能力。GDP 统计示例中还同时关闭了搜索与每页条数选择器,聚焦纯粹的排序体验:

if (document.getElementById("sorting-table") && typeof simpleDatatables.DataTable !== 'undefined') { const dataTable = new simpleDatatables.DataTable("#sorting-table", { searchable: false, perPageSelect: false, sortable: true }); }
<table id="sorting-table"> <thead> <tr> <th><span class="flex items-center">Country</span></th> <th><span class="flex items-center">GDP</span></th> <th><span class="flex items-center">Population</span></th> <th><span class="flex items-center">GDP per Capita</span></th> </tr> </thead> <tbody> <tr> <td class="font-medium text-heading whitespace-nowrap">United States</td> <td>$21433 billion</td> <td>331 million</td> <td>$64763</td> </tr> <tr> <td class="font-medium text-heading whitespace-nowrap">China</td> <td>$14342 billion</td> <td>1441 million</td> <td>$9957</td> </tr> <!-- 其余国家行见 content/plugins/datatables.md --> </tbody> </table>

关于排序的视觉反馈:Flowbite 插件定义了.datatable-sorter:hover以及.datatable-ascending .datatable-sorter、.datatable-descending .datatable-sorter的着色规则(见 plugin.js),因此表头中的箭头图标会在排序状态变化时自动高亮为标题色。

分页控制:每页条数与页码选项

分页对所有 Flowbite Datatables默认开启;如需关闭可设置paging: false。通过perPage指定默认每页展示的数据行数,通过perPageSelect自定义每页条数的下拉选项:

if (document.getElementById("pagination-table") && typeof simpleDatatables.DataTable !== 'undefined') { const dataTable = new simpleDatatables.DataTable("#pagination-table", { paging: true, perPage: 5, perPageSelect: [5, 10, 15, 20, 25], sortable: false }); }
<table id="pagination-table"> <thead> <tr> <th><span class="flex items-center">Model Name</span></th> <th><span class="flex items-center">Developer</span></th> <th>if (document.getElementById("selection-table") && typeof simpleDatatables.DataTable !== 'undefined') { let multiSelect = true; let rowNavigation = false; let table = null; const resetTable = function() { if (table) { table.destroy(); } const options = { rowRender: (row, tr, _index) => { if (!tr.attributes) { tr.attributes = {}; } if (!tr.attributes.class) { tr.attributes.class = ""; } if (row.selected) { tr.attributes.class += " selected"; } else { tr.attributes.class = tr.attributes.class.replace(" selected", ""); } return tr; } }; if (rowNavigation) { options.rowNavigation = true; options.tabIndex = 1; } table = new simpleDatatables.DataTable("#selection-table", options); // Mark all rows as unselected table.data.data.forEach(data => { data.selected = false; }); table.on("datatable.selectrow", (rowIndex, event) => { event.preventDefault(); const row = table.data.data[rowIndex]; if (row.selected) { row.selected = false; } else { if (!multiSelect) { table.data.data.forEach(data => { data.selected = false; }); } row.selected = true; } table.update(); }); }; // Row navigation makes no sense on mobile, so we deactivate it and hide the checkbox. const isMobile = window.matchMedia("(any-pointer:coarse)").matches; if (isMobile) { rowNavigation = false; } resetTable(); }
<table id="selection-table"> <thead> <tr> <th><span class="flex items-center">Name</span></th> <th>if (document.getElementById("export-table") && typeof simpleDatatables.DataTable !== 'undefined') { const exportCustomCSV = function(dataTable, userOptions = {}) { // A modified CSV export that includes a row of minuses at the start and end. const clonedUserOptions = { ...userOptions } clonedUserOptions.download = false const csv = simpleDatatables.exportCSV(dataTable, clonedUserOptions) // If CSV didn't work, exit. if (!csv) { return false } const defaults = { download: true, lineDelimiter: "\n", columnDelimiter: ";" } const options = { ...defaults, ...clonedUserOptions } const separatorRow = Array(dataTable.data.headings.filter((_heading, index) => !dataTable.columns.settings[index]?.hidden).length) .fill("+") .join("+"); // Use "+" as the delimiter const str = separatorRow + options.lineDelimiter + csv + options.lineDelimiter + separatorRow; if (userOptions.download) { // Create a link to trigger the download const link = document.createElement("a"); link.href = encodeURI("data:text/csv;charset=utf-8," + str); link.download = (options.filename || "datatable_export") + ".txt"; // Append the link document.body.appendChild(link); // Trigger the download link.click(); // Remove the link document.body.removeChild(link); } return str } const table = new simpleDatatables.DataTable("#export-table", { template: (options, dom) => "<div class='" + options.classes.top + "'>" + "<div class='flex flex-col sm:flex-row sm:items-center space-y-4 sm:space-y-0 sm:space-x-3 rtl:space-x-reverse w-full sm:w-auto'>" + (options.paging && options.perPageSelect ? "<div class='" + options.classes.dropdown + "'>" + "<label>" + "<select class='" + options.classes.selector + "'></select> " + options.labels.perPage + "</label>" + "</div>" : "" ) + "<button id='exportDropdownButton' type='button' class='flex w-full sm:w-auto text-body bg-neutral-secondary-medium box-border border border-default-medium hover:bg-neutral-tertiary-medium hover:text-heading focus:ring-4 focus:ring-neutral-tertiary shadow-xs font-medium leading-5 rounded-base text-sm px-3 py-2 focus:outline-none'>" + "Export as" + "<svg class='-me-0.5 ms-1.5 h-4 w-4' aria-hidden='true' xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' viewBox='0 0 24 24'>" + "<path stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m19 9-7 7-7-7' />" + "</svg>" + "</button>" + "<div id='exportDropdown' class='z-10 hidden w-52 divide-y divide-gray-100 rounded-lg bg-white shadow-sm dark:bg-gray-700'><table id="export-table"> <thead> <tr> <th><span class="flex items-center">Name</span></th> <th>// 通过 CDN 安装时的写法 const dataTable = new simpleDatatables.DataTable("#default-table"); // 通过 NPM 安装时的写法 import { DataTable } from "simple-datatables"; const dataTable = DataTable("#default-table");

第二个参数可以传入一个选项对象,用于自定义表格外观与行为:

const dataTable = new simpleDatatables.DataTable("#default-table", options);

初始化完成后即可访问实例暴露的方法与属性(如dataTable.search()、dataTable.insert()、dataTable.update()、dataTable.on()、dataTable.destroy()等,simple-datatables 官方文档提供了完整的公开方法与属性列表,本文不再赘述)。

常用选项详解

以下按功能分组梳理文档中推荐的常用选项。

注入数据(data)

使用data选项,可通过 JavaScript 以"数组的数组"形式向表格注入数据——相比硬编码 HTML,更适合从 API 或 JSON 文件动态加载:

const customData = { "headings": [ "Name", "Company", "Date", ], "data": [ [ "Flowbite", "Bergside", "05/23/2023", ], [ "Next.js", "Vercel", "03/12/2024", ], }; const dataTable = new DataTable("#default-table", { data: customData });

外观定制(Appearance)

以下选项用于定制表格外观:标题(caption)、自定义类(classes)、表尾(footer)、表头(header)、HTML 渲染模板(template)以及纵向滚动(scrollY):

const dataTable = new DataTable("#default-table", { caption: "Flowbite is an open-source library", classes: { // 自定义 HTML 类;完整列表见 simple-datatables 文档 // 建议在默认类之外追加,因为 Flowbite 依赖默认类来套用样式 }, footer: true, // 启用或禁用表尾 header: true, // 启用或禁用表头 labels: { // 自定义标签文案;完整列表见 simple-datatables 文档 }, template: (options, dom) => { // 自定义表格 HTML 模板;完整列表见 simple-datatables 文档 }, scrollY: "300px", // 启用纵向滚动(超出后内部滚动) });

这些选项非常适用于向动态生成的表头或表尾中注入自定义 HTML 元素——上文"导出文件"示例就是在template中挂载导出菜单的。

分页(Pagination)

const dataTable = new DataTable("#default-table", { paging: true, // 启用或禁用分页 perPage: 10, // 每页展示的数据行数 perPageSelect: [5, 10, 20, 50], // 每页行数的下拉选项 firstLast: true, // 启用或禁用首页/末页按钮 nextPrev: true, // 启用或禁用上一页/下一页按钮 });

当数据集较大时,分页是将其拆分为多页展示的有效手段。

搜索(Searching)

const dataTable = new DataTable("#default-table", { searchable: true, // 启用或禁用搜索 sensitivity: "base", // 搜索敏感度(base、accent、case、variant) searchQuerySeparator: " ", // 搜索查询的分隔符 });

注意原文档代码中sensitivity与searchQuerySeparator行之间缺少逗号,实际使用时请补全为如上格式。当数据集较大时,搜索功能帮助用户快速定位目标行。

排序(Sorting)

const dataTable = new DataTable("#default-table", { sortable: true, // 启用或禁用排序 locale: "en-US", // 排序所用区域设置 numeric: true, // 启用或禁用数值排序 caseFirst: "false", // 大小写优先级(upper、lower) ignorePunctuation: true, // 排序时是否忽略标点 });

当用户需要按指定列重排行序时,排序功能非常实用。

常用实例方法

以下是在初始化之后与 DataTable 实例交互的常见方法:

// 以编程方式搜索表格,其中 "term" 为查询字符串 dataTable.search(term, columns); // 向表格追加一行数据(假设表格有四个列) dataTable.insert({ "Heading 1": "Cell 1", "Heading 2": "Cell 2", "Heading 3": "Cell 3", "Heading 4": "Cell 4", }); // 更新表格的 DOM dataTable.update();

除此之外,simple-datatables 还暴露了on(事件监听)、destroy(销毁实例)等方法,完整列表可参考其官方文档中的 Methods 章节。

许可证说明

Flowbite 在上述示例中构建的所有代码均开源并遵循MIT 许可;simple-datatables 仓库同样开源,但其遵循GNU 许可。集成到商业项目前请分别确认两份许可证的条款。

小结

Flowbite Datatables 插件将 simple-datatables 的完整能力(搜索、排序、逐列过滤、分页、行选中与多格式导出)与 Tailwind CSS 的样式体系无缝衔接:只需安装依赖、复制 HTML 标记与配套 JavaScript,即可获得支持响应式、暗色模式与 RTL 的高性能数据表格,足以承载数千条数据的浏览与操作场景。若需在渲染层面进一步定制(例如注入自定义工具栏或动态加载数据),template、tableRender、data等选项以及search、insert、update、on等方法提供了充足的扩展空间,上述全部完整示例与数据行源码均可直接参考仓库中的 content/plugins/datatables.md 文件。

  • UI组件
  • 前端

【免费下载链接】flowbite

Open-source UI component library and front-end development framework based on Tailwind CSS

项目地址:https://gitcode.com/gh_mirrors/fl/flowbite
点击查看免费下载

相关推荐

上一篇:如何永久保存微信聊天记录:完整指南与智能分析方案
下一篇:jsPDF事件总线:实现PDF生成过程的解耦设计

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询