rj-grid
💡 为什么选 rj-grid
想象一下:一个 <rj-grid> 标签,就能替换掉你项目里那些「几万行就卡死、想加个分组又得换库」的表格——而不额外引入任何第三方依赖,也不用给商业表格库交授权费。
- 真·零依赖:运行时只需
vue,连可选的图表都是按需import('echarts')。不捆绑、不污染你的 lockfile。 - 小得离谱:gzip 约 110 KB,却装下了别人几个库加起来的功能量。
- 10 万行丝滑:行列双向虚拟滚动,实测 100,000 行 × 12 列秒开(生成仅约 12 ms)。
- 对标 AG Grid 全功能:树形 / 分组 / 透视 / SSRM / 公式 / 主题 / i18n / 导出 / NLQ 一应俱全。
- TypeScript 原生:完整的类型推导与
.d.ts,编辑器全程提示,不是「先跑起来再说」的糙活。 - 免费商用:MIT 协议,个人和企业都能放心用。
✨ 特性一览
| 分类 | 你会得到的能力 |
|---|---|
| 渲染 | 行列虚拟滚动(10 万行流畅)、冻结列、多级表头、密度三档、钉行、全宽行;单击单元格即选中行(selectOnCellClick,无需勾复选框;rangeSelection 开启时不生效,行选中走复选框) |
| 数据 | 客户端 / 分页 / 无限滚动 / SSRM 服务端行模型(按需块缓存)四种模式 |
| 分组 | 树形任意深度、拖拽分组、多级分组 + 组页脚聚合、列透视(含高基数护栏) |
| 编辑 | 8 类编辑器、校验、撤销/重做、批量事务回填、内置新增/编辑行弹窗 |
| 公式 | 零依赖 Excel 风格公式:=B2*C2、SUM/COUNTIF/SUMIF、区域引用、循环引用检测 |
| 筛选 | 列头漏斗 / 浮动筛选行 / 快速搜索 / 高级过滤(跨列 AND/OR 表达式树)四路叠加 |
| 外观 | 主题引擎(4 预设 × 明暗 × 强调色 × 自定义 CSS 变量)、i18n(中/英 + 文案覆盖)、图标替换 |
| 输出 | 打印 / CSV / Excel / PDF,支持选中行 / 当前视图 / 后端导出三种范围;四个按钮可逐个显隐(showPrint/showCsv/showPdf/showExcel);Excel 导入(showImport,v1.1.0+,默认不显示)内置「下载模板 → 选文件 → 开始导入」弹框,File 原样交 importFile 回调上传,组件不解析也不碰接口;弹框内可挂宿主自定义选项(importExtraFields,v1.1.1+,勾选/下拉) |
| 扩展 | 列上声明 actions 即得带边框操作按钮(超宽自动收进「⋯」);网格上声明 contextMenus 即得自定义右键菜单(子菜单/确认/危险项),都是声明式数组;右键行自带内置「查看该行 JSON」主题化弹层,宿主零接入 |
| AI | 纯离线确定性 NLQ,中英双语随 i18n 切换:中文用「数量大于50 按单价降序」、英文用 qty > 50 sort by price desc,回显随语言 |
| 状态 | stateKey 自动持久化 + getState/setState 编程式存取,刷新不丢视图 |
🚀 快速开始
三步,两分钟,跑起来。
① 安装
npm install rj-grid
# 或 pnpm add rj-grid / yarn add rj-grid
② 引入组件与样式
// main.ts —— 样式全局引一次即可
import 'rj-grid/style.css'
③ 直接使用
<template>
<rj-grid :columns="cols" :rows="rows" row-key="id" :height="480" show-toolbar />
</template>
<script setup lang="ts">
import { RjGrid } from 'rj-grid' // ⚠️ 必须「值导入」,不能只写 type
import type { RjColumn, RjRowData } from 'rj-grid'
const cols: RjColumn[] = [
{ field: 'name', title: '名称', width: 160, filter: 'text' },
{ field: 'qty', title: '数量', type: 'num', aggFunc: 'sum' },
{ field: 'price', title: '单价', type: 'money', aggFunc: 'avg' }
]
const rows: RjRowData[] = [
{ id: 1, name: '轴承', qty: 100, price: 12.5 },
{ id: 2, name: '电机', qty: 30, price: 480 }
]
</script>
show-toolbar 一开,冻结列、分组、筛选、导出、列显隐全部自带,无需再写一行代码。想解锁更多能力,加个属性即可 —— 每个特性的完整参数见 📖 使用手册。
🎬 能力演示
真实产品截图/动图,全部来自 playground 演示页:
🖱️ 两行代码做扩展:操作按钮 + 自定义右键菜单
不写插槽、不写渲染器——声明一个数组就够(完整参数见 📖 使用手册)。
① 单元格操作按钮(col.actions):带边框按钮直接渲染在单元格里,超出列宽自动收进「⋯」下拉;disabled/visible/confirm 支持按行求值:
const cols: RjColumn[] = [
// ...
{
field: 'op', title: '操作', width: 120, fixed: 'right',
actions: [
{ name: 'edit', label: '编辑', icon: '✎', onClick: (p) => openEdit(p.row) },
{ name: 'del', label: '删除', danger: true,
confirm: (p) => `确认删除 ${p.row.name}?`, // 走内置确认框
visible: (p) => p.row.status !== 'LOCKED', // 按行显隐
onClick: (p) => remove(p.row) }
]
}
]
② 自定义右键菜单(contextMenus,v0.3.0+):与 actions 同风格的声明式数组,自动追加在内置菜单项(复制/编辑/选择行)之后;声明了它就自动启用右键菜单,无需再开 contextMenu 属性:
<rj-grid :columns="cols" :rows="rows" :context-menus="contextMenus" />
import type { RjContextMenuItem } from 'rj-grid'
const contextMenus: RjContextMenuItem[] = [
{ name: 'copyCode', icon: '⧉', label: '复制物料编码', visible: (c) => !!c.row?.code,
onClick: (c) => navigator.clipboard?.writeText(String(c.row.code)) },
{ name: 'tools', label: '更多工具', children: [ // 一级子菜单,悬停展开
{ name: 'audit', label: '审计日志', onClick: (c) => audit(c.rowIndex) }
]},
{ name: 'del', icon: '🗑', label: '删除该行', danger: true, // 红色危险项
visible: (c) => !!c.row, // 右键空白区/分组行时不出现
confirm: '确认删除该行?',
onClick: (c) => c.api?.applyTransaction({ remove: [c.row] }) }
]
回调上下文 c 携带 { row, column, colId, rowIndex, value, api, event };每项点击同时派发 @context-menu-action 事件(附 item),不接 onClick 也能在网格层统一监听。旧版 contextMenu 函数式入参仍兼容,两者可共存。
③ 内置行 JSON 查看器(rowJson,v0.3.3+):右键菜单自带「查看该行 JSON」项(命中数据行时出现,无需任何配置),弹出与表格同主题的内置弹层:格式化 JSON、可选中、一键复制、点遮罩/关闭退出,循环引用等脏数据自动降级不会报错。不需要时用 :row-json="false" 关掉:
<!-- 默认即有:右键数据行 → 「查看该行 JSON」→ 主题化弹层(明暗自动跟随) -->
<rj-grid :columns="cols" :rows="rows" row-key="id" :context-menu="true" />
<!-- 不想要这个内置项 -->
<rj-grid :columns="cols" :rows="rows" row-key="id" :row-json="false" />
④ 右键不拦复制粘贴(v0.3.4+):组件菜单只接管行上的普通右键;表外空白区、编辑器/筛选输入框内、以及选中文字后的右键,都直接放行浏览器原生菜单——选中单元格里的值右键复制,再粘贴到筛选框、查询栏不受任何影响。
⬆ 导入 Excel:一个开关 + 一个回调 + 可选附加字段(v1.1.0+ / v1.1.1+)
工具栏「导入」按钮默认不显示(导入是往后台写数据的高危入口,宿主接了才该露出来,也不受 exportable 约束)。点开后是内置导入弹框:下载模板 → 选(或拖)Excel 文件 → 开始导入。组件不解析 Excel、也不碰接口——只把你选中的 File 原样交给 importFile 回调,后台要什么列顺、走哪个接口全由你定:
<template>
<rj-grid
ref="gridRef" :columns="cols" :rows="rows" row-key="id"
show-import :import-file="onImportFile" import-template="/wms/item/importTemplate"
:import-extra-fields="extraFields"
/>
</template>
<script setup lang="ts">
import type { RjImportExtraField } from 'rj-grid'
// 弹框里的附加选项(v1.1.1+):需要「覆盖已存在」这类开关时不必再弹二次确认
const extraFields: RjImportExtraField[] = [
{ key: 'updateSupport', label: '覆盖已存在(仅更新非空单元格)', kind: 'checkbox', defaultValue: false },
{ key: 'ownerDept', label: '归属部门', kind: 'select', defaultValue: 'WH',
options: [{ value: 'WH', label: '仓储部' }, { value: 'QC', label: '质检部' }] }
]
async function onImportFile(file: File, extras: Record<string, unknown>) {
const form = new FormData()
form.append('file', file)
form.append('updateSupport', String(!!extras.updateSupport)) // 弹框里勾的值直接跟着回来(select 回的是 value)
const res = await importItem(form)
if (res.code !== 0) throw new Error(res.msg) // 抛错 → 弹框不关,原地红字显示后台原因
gridRef.value?.refresh() // 导入成功后重取数
}
</script>
模板不想要后台那一套就不传 importTemplate:组件会按屏上可见列自己生成一个 xlsx 表头模板(导出去改完再导回来,列顺序天然对得上);也可以传函数并 return res.blob() 把后台模板流交给组件存盘。只接受 .xlsx / .xls,选错类型、未选文件、上传中都各有明确提示与禁用态(上传中连附加字段一起禁改,失败重试时字段值不丢);完整参数与更多示例见 📖 使用手册 §9.6。
🔍 与 AG Grid 对比
| 维度 | rj-grid | AG Grid |
|---|---|---|
| 授权 / 费用 | ✅ MIT 完全免费 | ⚠️ 企业级特性需商业授权 |
| 第三方运行时依赖 | ✅ 仅 vue |
⚠️ 自带框架与模块体系 |
| gzip 体积 | ✅ 约 110 KB | 显著更大 |
| Vue 3 原生 | ✅ 值导入即用,非二次封装 | 提供 Vue 封装层 |
| 离线自然语言查询 | ✅ 内置纯确定性 NLQ | ❌ 无 |
| 虚拟滚动 / 分组 / 透视 / SSRM / 公式 / 主题 / 导出 | ✅ 全部内置 | ✅ 部分在付费版 |
rj-grid 的定位不是「山寨 AG Grid」,而是给 Vue 项目一个免费、轻量、开箱即用的高质量选择。
🧩 数据模式(按需选择)
<!-- 客户端:全量入 rows,排序/筛选/分组全在浏览器,虚拟滚动扛 10 万行 -->
<rj-grid :columns="cols" :rows="rows" row-key="id" />
<!-- 分页:后端分页,loadData 自动携带排序/筛选/页码,分页器位置由 pager-position 决定 -->
<rj-grid :columns="cols" data-mode="pagination" :load-data="loadData" :page-size="20" />
<!-- 无限滚动:滚动到底按块续取,无页码 -->
<rj-grid :columns="cols" data-mode="infinite" :load-data="loadData" />
<!-- SSRM 服务端行模型:分组/大数据块缓存,按需分块加载 -->
<rj-grid :columns="cols" data-mode="serverSide" :load-data="loadData" server-side-grouping />
import type { RjLoadServerParams } from 'rj-grid'
// params 自动带 start/end/page/pageSize/sort/filters/quickFilterText/rowGroup…,平铺给后端即可
async function loadData(p: RjLoadServerParams) {
const res = await api.queryPage(p)
return { rows: res.list, total: res.total, success: true }
}
各模式的完整配置与回调签名见 手册 §6 数据模式。
🛠 兼容性与技术栈
- 框架:Vue
^3.4.0(唯一必装 peer 依赖) - 可选:
echarts >= 5.0.0(仅「集成图表」对话框用到,未安装时优雅降级不崩页) - 语言:TypeScript 全量类型,
.d.ts随包发布 - 样式:单一
rj-grid/style.css,主题走 CSS 变量,可按需覆盖 - 构建:Vite 库模式 ESM 单文件,
sideEffects仅 CSS,Tree-shaking 友好
🖥 本地运行演示页
演示页(playground/)独立起服、不依赖宿主项目,8 个标签就是能力地图:
git clone https://github.com/rjding/rjGrid.git # 国内可用镜像:git clone https://gitee.com/rjding/rj-grid.git
cd rjGrid
pnpm install
pnpm dev # 默认 http://localhost:5173
① 综合功能 ② 大数据性能 ③ 树形/分组/透视 ④ 服务端模式 ⑤ SSRM 块缓存 ⑥ 公式引擎 ⑦ 主题 & 国际化 ⑧ AI 自然语言查询
仓库布局
| 路径 | 作用 |
|---|---|
index.ts |
包入口(值导出 RjGrid + NLQ / 查询条件内核 + 全部公共类型) |
src/ |
组件与引擎源码(src/types.ts 是类型权威) |
__tests__/ |
407 个单测用例,入口 __tests__/run.ts |
build/rjDistCheck.mjs |
产物体检五守卫(构建末尾自动跑) |
vite.lib.config.ts |
库构建:ESM 单文件 + 单 style.css,external vue/echarts,不出 sourcemap |
playground/ |
8 标签演示页 |
docs/RjGrid使用手册.md |
完整使用手册(能力、API、坑与边界) |
dist/ |
发布产物,随库入库 |
开发命令
pnpm test # 单测 407 passed
pnpm ts # vue-tsc --noEmit
pnpm lint # eslint + stylelint
pnpm build # vite lib → vue-tsc 产 d.ts → 产物体检五守卫
pnpm size # 体积报告
pnpm dev # playground 演示页
发布新版本
改完源码 → npm version patch|minor|major(自动 bump + commit + tag)→ git push --follow-tags → npm publish(prepublishOnly 会自动 pnpm build && pnpm test,杜绝发出旧 dist)。
宿主接入补充
- 从 npm 安装目录名规范(
node_modules/rj-grid),样式可直接import 'rj-grid/style.css'。 - 组件侧必须值导入
import { RjGrid } from 'rj-grid',只写 type 导入会在运行期报Failed to resolve component: rj-grid。 - 走 git URL 时 pnpm 会把依赖装进带
#<commit>的目录名,vite 资源 URL 含裸#会被当片段丢掉 → dev 下 404,此时用 CSS@import垫片(详见手册 §15.4)。 dist入库仅为兼容 git URL 安装路径;sourcemap: false是源码保护而非可选项,产物五守卫同时在把关。
🤝 贡献
欢迎 Issue 与 PR:提 bug、要特性、补文档都行。改动请附带相应单测,保证 pnpm test && pnpm ts && pnpm lint && pnpm build 全绿。
📄 许可证
MIT — 个人与企业均可免费使用、修改与再分发。
☕ 支持作者
如果 rj-grid 帮到了你,欢迎点个 ⭐ Star,或请作者喝杯咖啡:
Related Packages
Vue 3 component for FreeGrid, the fast data grid. Free core; paid features free...
Data table with customizable features including inline editing, summary data, pa...
Version History
| Version | Released | License |
|---|---|---|
| 1.1.1 | MIT | |
| 1.1.0 | MIT | |
| 0.3.5 | MIT | |
| 0.3.4 | MIT | |
| 0.3.3 | MIT | |
| 0.3.2 | MIT | |
| 0.3.1 | MIT | |
| 0.3.0 | MIT | |
| 0.2.11 | MIT | |
| 0.2.10 | MIT | |
| 0.2.9 | MIT | |
| 0.2.8 | MIT | |
| 0.2.7 | MIT | |
| 0.2.6 | MIT | |
| 0.2.5 | MIT | |
| 0.2.4 | MIT | |
| 0.2.3 | MIT | |
| 0.2.2 | MIT | |
| 0.2.1 | MIT | |
| 0.2.0 | MIT | |
| 0.1.0 | MIT |