VanillaDataGrid
零依赖、单文件JavaScript数据网格。完全响应、轻量级、可访问和无框架。
功能 • 安装 • 快速入门 • 文档 • 服务器端加载 • API &选项
功能
- 零依赖关系 -纯JS (IIFE经典脚本,不需要构建系统、打包器或包管理器)。
- 双数据模式 -与现有的HTML完全在内存中工作
<table>行,或通过Ajax动态加载。 - 丰富的互动 -不区分大小写搜索,每页可调整行数,键入排序(
string,number,date使用blank -last语义)和窗口分页。 - 列控制 -通过可访问的下拉菜单切换列可见性。
- 出口及印刷 —导出为CSV(含UTF-8 BOM和CRLF)、JSON,或打开干净打印视图。
- 可使用的 -键盘可排序的标头(
aria-sort),aria-current分页,一个带有实时信息区域的动画加载指示器(aria-live),以及焦点管理。 - 安全可靠 -支持通过取消请求
AbortController,页面夹紧,双初始化保护,完成destroy()清理。
安装
从npm安装:
npm install @languaojs/vanilladatagrid
然后从页面中引用已发布的文件:
<link rel="stylesheet" href="./node_modules/@languaojs/vanilladatagrid/src/datagrid.css">
<script src="./node_modules/@languaojs/vanilladatagrid/src/datagrid.js"></script>
或者使用unpkg CDN中的版本文件:
<link rel="stylesheet" href="https://unpkg.com/@languaojs/vanilladatagrid/src/datagrid.css">
<script src="https://unpkg.com/@languaojs/vanilladatagrid/src/datagrid.js"></script>
datagrid.js 是一个经典的浏览器脚本,而不是CommonJS或ES模块。它分配 globalThis.VanillaDataGrid (连同已弃用的 VanillaDataTable 别名)。不要装 type="module";使用常规的 <script> 标签。
快速入门
1. 本地表(内存中)
使用以下命令配置列 data-field, data-sortable="true", data-type 在 <thead><th>:
<table id="users">
<thead>
<tr>
<th data-field="name" data-sortable="true">Name</th>
<th data-field="role" data-sortable="true">Role</th>
<th data-field="score" data-sortable="true" data-type="number">Score</th>
</tr>
</thead>
<tbody>
<tr><td>Ada Lovelace</td><td>Engineer</td><td>98</td></tr>
<tr><td>Grace Hopper</td><td>Admiral</td><td>92</td></tr>
</tbody>
</table>
<script src="datagrid.js"></script>
<script>
const grid = new VanillaDataGrid('#users', {
rowsPerPage: 5,
export: true
});
</script>
2. 远程表(Ajax)
将网格指向端点(ajaxUrl)或提供自定义获取函数(ajax):
const grid = new VanillaDataGrid('#users', {
ajaxUrl: '/api/users', // GET /api/users?page=1&limit=10&search=&sort=&order=
rowsPerPage: 10,
export: true
});
服务器端加载
grid期望后端端点返回与此契约匹配的JSON:
{
"total": 57,
"rows": [
["Ada Lovelace", "Engineer", "98", "2021-03-14", "Active"],
{
"attributes": { "data-user-id": "2", "class": "featured" },
"cells": [
{
"html": "<strong data-kind=\"first-name\">Grace</strong> Hopper",
"text": "Grace Hopper",
"attributes": { "data-column": "name", "title": "Grace Hopper" }
},
"Admiral", "92", "2019-11-08", "Active"
]
}
]
}
对于本地HTML表,保留嵌套的单元格标记及其属性 <tr> 和 <td>/<th> 属性。表部分和表头保持不变,其属性和标记保持不变。Ajax行可以是单元格数组或对象 cells 数组和行 attributes;每个单元可以提供 html, text, attributes, tagName ("td" 或者 "th"). 中提供相同的行和单元元数据 grid.getState().rows. 标记和属性按照提供的方式呈现,因此只使用受信任的HTML和属性。
PHP示例(/api/users.php)
<?php
header('Content-Type: application/json; charset=utf-8');
$page = max(1, (int)($_GET['page'] ?? 1));
$limit = min(100, max(1, (int)($_GET['limit'] ?? 10)));
$search = trim($_GET['search'] ?? '');
$offset = ($page - 1) * $limit;
// Example query with PDO
$stmt = $pdo->prepare('SELECT name, role, score, joined, status FROM users WHERE name LIKE ? LIMIT ? OFFSET ?');
$stmt->execute(["%$search%", $limit, $offset]);
$count = $pdo->prepare('SELECT COUNT(*) FROM users WHERE name LIKE ?');
$count->execute(["%$search%"]);
echo json_encode([
'total' => (int)$count->fetchColumn(),
'rows' => $stmt->fetchAll(PDO::FETCH_NUM)
]);
Node.js / Express示例
app.get('/api/users', async (req, res) => {
const page = Math.max(1, Number(req.query.page) || 1);
const limit = Math.min(100, Math.max(1, Number(req.query.limit) || 10));
const search = req.query.search || '';
// Fetch rows and total count from your database...
res.json({
total: totalCount,
rows: rows.map(u => [u.name, u.role, u.score, u.joined, u.status])
});
});
选项与配置
const grid = new VanillaDataGrid('#table-id', {
rowsPerPage: 5, // Default page size
showRowsPerPage: true, // Show the rows-per-page input beside search
ajaxUrl: null, // Endpoint URL string (or null for local mode)
ajax: null, // Optional custom function: async ({ page, size, query, sort, order, signal }) => ({ rows, total })
fetchOptions: {}, // Custom fetch options (headers, credentials, etc.)
export: true, // Enable exports: true (all formats), false, or ['csv', 'json', 'print']
exportFilename: 'export', // Base download filename
exportScope: 'page', // Remote export scope: 'page' (default) or 'all' (walks pages)
maxExportRows: 10000, // Safety limit for exportScope: 'all'
searchDebounce: 300, // Search input debounce delay in ms
labels: {}, // UI string overrides & custom info formatter
columns: null // Optional column configuration overrides
});
默认情况下,每页行数输入显示在搜索旁边。集 showRowsPerPage: false 隐藏它,同时保持配置的页面大小。 rowsPerPage 设置初始值;如果省略,则默认为10。
API方法
grid.reload({ resetPage })-重新加载当前数据源(可选择重置到第1页)。grid.search(term)-以编程方式执行搜索查询。grid.sort(index, 'asc' | 'desc')—按列索引排序。grid.goToPage(n)-导航到页面n.grid.setColumnVisible(index, boolean)—显示或隐藏列。grid.setData(rows)—替换本地行(仅限本地模式)。grid.getExportData()——返回{ headers, rows }用于出口。grid.exportCSV()—触发CSV下载。grid.exportJSON()—触发JSON下载。grid.printTable()-打开打印窗口。grid.getState()-返回当前内部状态的深度克隆。grid.destroy()-删除控件,取消包装表,中止活动请求/监听器,并恢复原始标记。
事件
事件从底层表元素冒泡产生:
vdg:load-当数据成功渲染时触发(detail:{ grid, rows, total, page, query, sort })。vdg:error-在装载或导出失败时触发(detail:{ grid, error, action })。vdg:page-更改页面时触发(detail:{ grid, page })。vdg:sort-在排序(detail:{ grid, index, dir, field })。vdg:search-搜索时被触发(detail:{ grid, query })。vdg:column-当列可见性改变时触发(detail:{ grid, index, visible, field })。vdg:export-导出完成时触发(detail:{ grid, format, rows })。
支持及捐赠
如果您发现VanillaDataGrid对您的项目有帮助,请考虑通过捐赠来支持其维护:
许可证
麻省理工学院