☰
ag-grid-community 安装避坑:样式、模块注册与版本对齐
2026/11/5 4:59:14 网站建设 项目流程

简介:面向使用 JavaScript、React、AngularJS 与 Web Components 的前端开发者,这是一份 ag-Grid Community 开源数据网格库的源码与示例素材包,适合需要处理海量数据表格、自定义单元格渲染、排序过滤分组、分页和编辑校验等场景的中级开发人员参考,对复杂表格交互与大数据量展示有较完整的覆盖。压缩包内共 2000 个文件,以 js、ts、html、css、json 等前端源码和配置为主,并包含 png、svg、gif 等界面与说明素材,以及少量 php、java 辅助文件,整体约 190.14MB,目录素材较丰富,便于按模块查阅与对照。已有 1464 人学习或下载。读者可据此了解网格初始化、列定义、运行时 API、事件系统和主题定制等实现方式,也能结合示例页面与样式资源对照组件行为,适合作为搭建后台数据表格、研究虚拟化渲染和框架集成方案的参考资料,并帮助理解常见配置项的用途。

1. 一张只有表头、下面是空白的表格:ag-grid-community 装错的第一步在哪

去年冬天有个中后台项目,本地npm run dev跑得好好的,表格能滚、能排序、能筛;打进测试环境之后表头还在,下面一片空白,控制台干干净净,什么报错都没有。查了半天,原因是构建时把样式表 tree-shake 掉了一半,加上列定义里的模块没注册。ag-grid-community 这个前端开源表格库接入面很广,React、Vue、Angular、原生 JS 都能用,正因为“都能用”,装错的路子也格外多:样式漏引、模块没注册、框架封装包和核心包主版本号对不上,症状各不相同,但最终表现都是“表格不显示”。

它适合数据量上万、需要虚拟滚动、列固定、行分组、服务端分页的中后台表格页;如果只是渲染十几行静态数据,引它纯属给自己加负担。下面的顺序是:先看清要装哪几个包、环境底线在哪,再跑起来一张最小的表,然后拆配置,最后把我装坏过的几次和验收方法摊开。

2. 环境与包结构:Node、包管理器、适配包怎么选

2.1 Node 版本与包管理器的底线

ag-grid-community 本身是纯前端库,没有原生模块,理论上不挑 Node,但它的构建产物和类型声明是按现代语法打的,Node 太老会在安装阶段就报Unexpected token或者解析exports字段失败。我一般要求 Node 用当前 LTS 大版本,先确认一下:

node -v # 建议 LTS 大版本,非 LTS 的奇数额度容易在构建链路出问题 npm -v

包管理器更值得说。npm 和 yarn 走的是扁平化node_modules,一般不会出问题;pnpm 是软链接 + 严格依赖隔离,而 ag-grid 的新版把功能拆成了多个子包,框架适配包和核心包之间靠 peer 依赖互相找,隔离一严就容易出现“装是装了,但运行时找不到模块”。踩过这个坑之后,我在用 pnpm 的项目根目录固定放一个.npmrc:

# 把 ag-grid 相关的包提到根 node_modules,绕开软链接隔离 public-hoist-pattern[]=*ag-grid* # 实在搞不定时的保底方案,代价是失去严格隔离的好处 shamefully-hoist=true

public-hoist-pattern只对匹配到的包做提升,比shamefully-hoist温和,优先用前者。改完.npmrc必须删掉node_modules和 lockfile 重装,因为提升关系是在安装期算出来的,改配置不重装不生效。

2.2 社区版和企业版的分包差异:先看清依赖树

装之前先明确一件事:ag-grid 有社区版和企业版两套包。社区版就是你项目标题里那个ag-grid-community,MIT 授权,覆盖排序、筛选、分页、虚拟滚动、列固定、CSV 导出这些常规能力;企业版是另一个包名,行分组、透视表、服务端行模型、Excel 导出那些要它。新手最容易犯的错是“照着某篇教程装了企业版包名”,本地能跑,上线被授权校验卡住。先看一眼依赖树,确认自己装的是哪一挂:

# 列出当前工程里所有和 ag-grid 相关的包及其版本 npm ls ag-grid-community ag-grid-enterprise --depth=1

再看新版的分包结构。拆包之后的版本,核心逻辑在@ag-grid-community/core,每一项功能单独成包,比如客户端行模型、文本筛选、分页各自一个。你在业务代码里通常只import顶层包名,但打包器解析到的是这些子包。这就带来两个直接后果:一是“我明明装了却报模块不存在”,多半是子包版本没对齐;二是“按需引入”从建议变成了必须做的事,全量引入会让首屏包体积明显变大。判断自己装的是拆包前还是拆包后,最直接的办法是看node_modules/@ag-grid-community/这个目录存不存在。

包名作用是否必需
ag-grid-community社区版入口包,业务代码主要 import 它必需
@ag-grid-community/core拆包后的核心实现,通常不直接 import随主包带出
ag-grid-react/ag-grid-vue3/ag-grid-angular框架声明式封装用对应框架时必需
ag-grid-enterprise企业能力包,有授权校验社区版场景不要装

2.3 框架适配包怎么挑,版本为什么必须对齐

选包只看一条:你的渲染层用什么。原生 JS 或不用框架的页面,只装ag-grid-community一个就够;React 项目装ag-grid-community+ag-grid-react;Vue 3 装ag-grid-community+ag-grid-vue3,Vue 2 用的是另一个包名,别混;Angular 装ag-grid-community+ag-grid-angular,后者会声明@angular/core的 peer 依赖,版本跨度太大安装期就警告。

# React 项目:核心包 + 框架封装包一起装 npm i ag-grid-community ag-grid-react # Vue 3 项目 npm i ag-grid-community ag-grid-vue3

这里有个血泪经验:两个包的主版本号必须一致。框架封装包内部是按核心包的 API 写的,核心包大版本一升,createGrid之类的入口签名可能变,封装包还按老签名调,表现就是组件挂载了、DOM 里也有容器,就是不渲染内容,控制台最多给你一句不痛不痒的 warn。装完立刻核对:

# 两个包的主版本号应当相同 npm ls ag-grid-community ag-grid-react

如果版本已经漂了,别手动去改node_modules,直接把两个包按同一个主版本重装,或者在package.json里用同一个^主版本前缀锁住,避免以后某次npm update又漂回去。

3. 从空目录到一张能滚动的表格:ag-grid-community 安装全程

3.1 建工程与安装命令

为了排除已有项目的干扰,先在一个空目录里跑通最小例子。下面用 Vite 起一个 React 工程,是最快能看到效果的方式:

# 建目录并初始化 mkdir grid-demo && cd grid-demo npm init -y # 起一个 Vite + React 的最小工程,跟着提示选 react 模板 npm create vite@latest . -- --template react # 装依赖 npm install # 装表格库 npm i ag-grid-community ag-grid-react # 启动 npm run dev

npm create vite@latest . -- --template react里的.表示在当前目录创建,双横线后面的参数透传给脚手架,--template react决定模板。如果目录里已经有package.json,脚手架会问你是否覆盖,选不覆盖、只补文件即可。项目已经有构建体系的话,跳过前三步,只执行npm i ag-grid-community ag-grid-react。

装完先别急着写业务,跑一次npm run dev,确认工程本身是能起的。这一点很多人省掉,结果后面表格不显示,分不清是插件的问题还是工程的问题。

3.2 样式表引入:两个文件一个都不能少

ag-grid 的样式拆成两份:一份是结构样式,负责行列布局、滚动容器、虚拟滚动的定位;另一份是主题样式,负责颜色、字号、边框这些观感。少引第一份,表格会塌成一堆没有高度的 div;少引第二份,能显示但没有任何配色,白底黑字挤在一起。

// 入口文件里引入,顺序不能反:先结构,后主题 import 'ag-grid-community/styles/ag-grid.css'; import 'ag-grid-community/styles/ag-theme-quartz.css';

路径这点要留个心:新版包内样式在styles/下,老版多在dist/styles/下,且主题名不一样——新版主推quartz,老版常见的是alpine、balham、material。引入的时候别凭记忆写路径,去node_modules/ag-grid-community/里看一眼实际目录,目录叫什么就写什么。

提示:主题 CSS 文件和你挂在容器上的类名必须成对。引了 quartz 的 css 却写className="ag-theme-alpine",框架不会报错,你只会看到一张完全没有主题效果的表格,排查起来很浪费时间。

3.3 最小可运行表格:列定义与行数据

React 封装包用起来是声明式的,核心就两个 props:rowData和columnDefs。

import { useMemo, useState } from 'react'; import { AgGridReact } from 'ag-grid-react'; import 'ag-grid-community/styles/ag-grid.css'; import 'ag-grid-community/styles/ag-theme-quartz.css'; export default function DemoTable() { // 行数据:字段名要和列定义里的 field 对上 const [rowData] = useState([ { id: 1, name: '示例行一', score: 92 }, { id: 2, name: '示例行二', score: 78 }, ]); // 列定义用 useMemo 固定引用,否则每次渲染都会生成新数组,触发列重建 const columnDefs = useMemo(() => [ { field: 'id', headerName: '编号', width: 90, sortable: true }, { field: 'name', headerName: '名称', flex: 1, minWidth: 160 }, { field: 'score', headerName: '分数', width: 120, filter: 'agNumberColumnFilter' }, ], []); // 容器必须有确定高度,否则虚拟滚动算不出可视区 return ( <div className="ag-theme-quartz" style={{ width: '100%', height: 480 }}> <AgGridReact rowData={rowData} columnDefs={columnDefs} /> </div> ); }

三处值得说。field是取值路径,写user.name这种嵌套路径也行,写错了单元格就是空的,但不报错;flex: 1让这一列吃掉剩余宽度,和固定width的列混用是做自适应表格的常规做法;外层容器的高度是硬要求,ag-grid 靠测量容器高度来决定渲染多少行,容器高度为 0 或者auto,结果就是只画表头。

不用框架的页面写法不一样,新版导出的是工厂函数:

import { createGrid, ModuleRegistry, ClientSideRowModelModule } from 'ag-grid-community'; import 'ag-grid-community/styles/ag-grid.css'; import 'ag-grid-community/styles/ag-theme-quartz.css'; // 拆包后的版本必须先注册模块,不然创建出来是个空壳 ModuleRegistry.registerModules([ClientSideRowModelModule]); const gridOptions = { columnDefs: [ { field: 'id', headerName: '编号', width: 90 }, { field: 'name', headerName: '名称', flex: 1 }, ], rowData: [ { id: 1, name: '示例行一' }, { id: 2, name: '示例行二' }, ], defaultColDef: { sortable: true, resizable: true }, // 全局默认列行为 }; createGrid(document.getElementById('myGrid'), gridOptions);

如果你手上的版本没有导出createGrid,那大概是拆包前的老版本,入口是new Grid(容器, 配置)这种构造式写法。判断方法很土但有效:在浏览器控制台里对这个模块打印一下,看导出了哪个。别在两个写法之间反复猜。

3.4 启动后先看这四处

npm run dev起来之后,别急着往下写业务,先按顺序看四件事:表头有没有渲染出来、两行数据在不在、拖动列宽有没有反应、在容器里滚动鼠标滚轮有没有出现纵向滚动条。这四件事分别对应样式结构、列定义映射、交互模块、虚拟滚动容器,任何一项挂了,问题范围立刻缩小一半。控制台如果有Module X is not registered这类告警,别忽略,那是模块注册没做全的直接提示。

4. 配置拆解:列定义、模块注册、主题变量三处

4.1 列定义里真正影响体验的字段

columnDefs是配置量最大的地方,但常用的就那么十几个。下面这张表是我每次接新项目都会过一遍的:

字段作用注意点
field取值路径支持a.b.c嵌套,写错不报错,只是空
headerName表头文案不写则用field原样展示
width/flex/minWidth宽度策略flex与固定width可混用,minWidth防挤没
sortable/resizable排序、拖宽建议放defaultColDef统一开
filter筛选器类型需注册对应筛选模块,否则筛选图标不出现
valueGetter派生列取值用于拼接字段或格式化前的原始值
cellRenderer自定义单元格返回组件或渲染函数,注意别在里面做重计算
pinned左右固定列取值left/right,移动端慎用
checkboxSelection行选择框配合rowSelection使用

我更倾向把公共行为放进defaultColDef,列上只写差异项:

const defaultColDef = { sortable: true, // 所有列默认可排序 resizable: true, // 所有列默认可拖宽 filter: true, // 所有列默认开启筛选 minWidth: 100, // 防止窄屏下把列压到看不见 flex: 0, // 默认不吃剩余宽度,交给具体列控制 };

这样做的直接收益是列定义短,改动集中。副作用是filter: true会给每一列都开筛选,列多的时候顶部图标很密,视觉上乱,通常我会在具体列上按需覆盖成false。

4.2 模块注册:按需引入与全量引入的取舍

拆包后的版本把功能切成模块,不注册就等于没这个能力。新手最常见的困惑是“我明明写了filter: true,筛选图标怎么不出现”,答案就是筛选模块没注册。按需注册写法如下:

import { ModuleRegistry, ClientSideRowModelModule, // 客户端行模型,最基础的一个 TextFilterModule, // 文本筛选 NumberFilterModule, // 数字筛选 PaginationModule, // 分页 CsvExportModule, // CSV 导出 } from 'ag-grid-community'; // 一次性注册,必须在创建表格之前执行 ModuleRegistry.registerModules([ ClientSideRowModelModule, TextFilterModule, NumberFilterModule, PaginationModule, CsvExportModule, ]);

这段代码通常放在应用入口,全局执行一次就够,不要放在组件内部,否则组件每次挂载都重复注册。取舍上:按需注册包体积小,但每加一个新功能都得回来补一行,漏了就是“功能静默失效”;全量引入省心,代价是首屏体积变大,中后台项目里这一项往往能接受,对外网首屏敏感的项目就得按需。我的习惯是先按需,等模块列表涨到十来项、维护成本明显上来,再评估切全量。

ClientSideRowModelModule是最容易漏的一个,因为其它模块都注册了、表格也能出来,唯独数据不显示,看起来像是数据结构的问题,实际是行模型没注册。

4.3 主题与样式覆盖:优先用 CSS 变量

主题不要直接去改 ag-grid 的类名,比如强行覆盖.ag-header-cell的样式。它的 DOM 结构在版本之间会变,写死的选择器升级就碎。正确做法是覆盖 CSS 变量,主题包暴露了一批--ag-前缀的变量:

/* 挂在主题容器上,只影响这一块表格 */ .ag-theme-quartz { --ag-font-size: 13px; /* 全局字号,行高会跟着算 */ --ag-header-background-color: #f5f7fa; /* 表头底色 */ --ag-row-hover-color: #eef4ff; /* 行悬停色 */ --ag-border-color: #e3e6eb; /* 分隔线颜色 */ --ag-cell-horizontal-padding: 12px; /* 单元格左右内边距 */ }

这套变量是主题契约的一部分,比覆盖类名稳。如果某个效果变量覆盖不到,再考虑写类名覆盖,并且在选择器上加容器前缀限定作用域,避免污染全局。

注意:样式覆盖文件要在主题 CSS 之后引入。构建工具按引入顺序合并样式,顺序反了会被主题默认值盖掉,表现是“我写了但没生效”。

4.4 大数据量下的行模型与分页配置

社区版可用的行模型主要是客户端行模型和无限滚动行模型。客户端行模型一次性拿到全量数据,靠虚拟滚动只渲染可视区,几万行以内都扛得住;数据量再往上、或者数据本身要按需拉取,就换成无限滚动,按块请求。服务端行模型属于企业版能力,社区版场景不要往那个方向设计。

const gridOptions = { rowModelType: 'clientSide', // 社区版常用;大数据按需拉取可换 'infinite' pagination: true, paginationPageSize: 50, // 每页行数 paginationPageSizeSelector: [20, 50, 100], rowBuffer: 10, // 可视区外多渲染的行数,调大可减少快速滚动白屏 cacheBlockSize: 100, // 无限滚动模型下每块请求的行数 suppressColumnVirtualisation: false, // 列很多时保持列虚拟化开启 };

rowBuffer是快速滚动时最值得调的一个参数,默认值偏保守,机器一般、用户又爱甩滚轮的项目里,调到 10 到 20 之间白屏感会明显减轻,代价是初始渲染多一些行。paginationPageSize别设太大,一页 500 行翻页时会明显卡一下,50 到 100 是比较稳的区间。

5. 避坑与排查:五条装坏之后的救法

5.1 只有表头没有数据行

现象:表头正常渲染,列名也对,容器下面一片白,控制台没有红色报错,最多一条黄色的模块告警。

原因:拆包版本下ClientSideRowModelModule没有注册,或者注册代码写在创建表格之后。行模型负责把rowData转成可视行,缺了它,表格有列无行。

解决:在应用入口、创建表格之前注册这个模块,然后重启 dev server。如果注册了还是不显示,下一步查容器高度是不是 0——打开元素面板看表格容器实际高度,高度塌了同样只画表头。

5.2 样式错乱,图标变成方块

现象:表格能显示,但排序箭头、筛选漏斗、展开三角全是方块或空白方框,行高也不对。

原因:结构样式表ag-grid.css引了、主题表没引,或者主题类名和引的主题文件不匹配;另一种情况是项目里有全局样式把font-family强设成了不含图标的字体,图标字体被顶掉。

解决:确认结构和主题两份 CSS 都引了、顺序是先结构后主题、容器上的ag-theme-xxx类名和引入的主题文件名一致。三步都对还是方块,就去查全局样式里的font-family通配规则,把它限定到具体容器上。

5.3 打包体积异常增大

现象:只加了一张表格页,构建产物比之前大了好几百 KB,首屏加载明显变慢。

原因:一是全量引入模块,把所有功能都打进包里;二是框架封装包和核心包的版本没对齐,导致核心包被打进两份;三是直接import了企业版包,把用不到的能力一起带进来。

解决:先跑一次构建分析,看 ag-grid 相关包实际占了多少、有没有重复;确认依赖树里只有一个主版本;然后按需注册模块,把筛选、导出这些非首屏必需的能力评估是否延后加载。

# 用 npm 自带的依赖树排查重复的 ag-grid 包 npm ls ag-grid-community ag-grid-react ag-grid-enterprise

如果输出里同一个包出现了两个不同主版本,说明锁文件里有残留,删node_modules和 lockfile 重装。

5.4 服务端渲染时报 document is not defined

现象:本地浏览器跑正常,一上服务端渲染就报document is not defined,构建阶段中断。

原因:ag-grid 要在浏览器里测量容器尺寸、创建 DOM,模块顶层也有对window、document的访问。服务端没有这些对象,导入即崩。

解决:把表格组件改成只在客户端加载,用动态导入避开服务端求值;同时确认注册模块的代码也放在客户端侧执行,不要放在服务端入口的顶层。

// 仅在客户端动态加载表格组件,避免服务端求值时报 document 未定义 import dynamic from 'next/dynamic'; const DemoTable = dynamic(() => import('./DemoTable'), { ssr: false, loading: () => <div style={{ height: 480 }}>加载中</div>, });

5.5 列宽拖动、筛选点了没反应

现象:表格能滚能选,但拖动列边框没有反馈,点筛选图标下拉不出来,排序点击也没变化。

原因:对应的功能模块没注册。拆包之后,排序、筛选、列宽调整这些交互都各自绑定模块,defaultColDef里写sortable: true只是声明意图,没有模块提供实现就静默失效。

解决:按实际用到的交互补注册对应模块,改完重启;如果用的是自定义筛选组件,还要确认该组件本身的模块依赖也注册全了。补完之后回到 3.4 那四处检查,重新过一遍。

6. 装完怎么验证:一张验收表和我的三步自检

装完不等于装对。我判断一套 ag-grid-community 环境是否真的可交付,不看页面能不能截个图,而是跑一遍下面这张表。每一项都能在浏览器里两分钟内点完,任何一项没过都说明还有一处配置没落地。

验收项操作通过标准
结构样式打开页面表头、数据行、边框齐全,无元素塌陷
主题生效比对设计稿主色表头底色、悬停色与设计一致
行模型看数据行行数与rowData一致,不是只有表头
虚拟滚动灌 5000 行后快速滚动不白屏,滚动条长度合理
排序点表头两次升降序切换,图标同步变化
筛选点筛选图标下拉能弹出,输入后行数变化
列宽拖列边框宽度变化,相邻列跟随
包体积跑一次构建分析没有重复的 ag-grid 主版本

三步自检我固定这么走。第一步是空数据起步:把rowData设成空数组,看表头能不能正常出来、列名对不对、空态提示有没有。空数据阶段就能暴露样式和列定义的问题,比灌了数据再排查干净得多。第二步灌入五千行假数据,专门看滚动,快速上下甩滚轮,看有没有大块白屏、有没有行卡住不刷新,这直接反映rowBuffer和虚拟滚动配置是否合适。第三步打开构建分析,确认包体积没有异常,尤其是有没有两个不同主版本的 ag-grid 同时被打进去——这个后悔药大家都不想在线上吃。

还有个小技巧:新建一个只含表格的空白页作为独立路由,不要一上来就塞进业务页面里。业务页面的全局样式、布局 flex、祖先容器高度都会干扰表格的表现,独立页能跑通,再去业务页接线,出问题时你可以立刻判断是插件的事还是页面布局的事。

从那以后我每次接 ag-grid,不管是新项目起盘还是往老项目里塞,都强制走一遍这三步——空数据看结构、灌数据看滚动、跑构建看体积。这套流程花不了二十分钟,省下来的排查时间大概率是它的好几倍。希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询