🚀 AG Grid 完整入门教程:从零开始掌握企业级数据表格
❓ 引言:为什么选择 AG Grid?
🎯 1.1 数据表格的重要性
在现代Web应用开发中,数据表格是展示和操作结构化数据的核心组件。无论是企业管理系统、数据分析平台还是CRM系统,都需要一个强大、灵活且高性能的表格组件来处理大量数据。
🌟 1.2 AG Grid 的独特优势
AG Grid 作为业界领先的JavaScript数据表格组件,具有以下显著优势:
✅ 卓越性能:采用虚拟滚动技术,轻松处理百万级数据 ✅ 功能丰富:内置排序、过滤、分组、聚合等数十种功能 ✅ 高度可定制:支持自定义渲染器、编辑器、样式等 ✅ 跨框架支持:支持原生JavaScript、React、Angular、Vue等 ✅ 企业级特性:提供企业版功能如Excel集成、高级过滤等
🎓 1.3 学习目标
通过本教程,您将能够:
- 快速集成 AG Grid 到您的项目中
- 掌握基础配置和常用功能
- 实现高级特性如分页、排序、过滤
- 自定义表格外观和行为
- 解决常见问题和性能优化
🛠️ 第一章:环境搭建与快速开始
📦 2.1 安装 AG Grid
✅2.1.1 通过 npm 安装
# 安装社区版(免费)
npm install ag-grid-community
# 安装 React 版本
npm install ag-grid-react
# 安装企业版(付费)
npm install ag-grid-enterprise
💡 老曹讲解: 这里展示了三种安装方式:
✅2.1.2 CDN 引入方式
<!DOCTYPE html>
<html>
<head>
<!– AG Grid 样式 –>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community/styles/ag-grid.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community/styles/ag-theme-alpine.css">
</head>
<body>
<!– AG Grid 脚本 –>
<script src="https://cdn.jsdelivr.net/npm/ag-grid-community/dist/ag-grid-community.min.js"></script>
</body>
</html>
💡 老曹讲解: 通过 CDN 快速引入 AG Grid 的方式:
- 必须引入两个 CSS 文件:基础样式和主题样式(这里使用 alpine 主题)
- 只需引入一个 JS 文件(社区版核心库) 适合快速原型开发或非构建工具项目
🚀 2.2 最简单的 AG Grid 示例
✅2.2.1 HTML + JavaScript 版本
<!DOCTYPE html>
<html>
<head>
<title>AG Grid Quick Start</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community/styles/ag-grid.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ag-grid-community/styles/ag-theme-alpine.css">
<style>
.ag-theme-alpine {
height: 500px;
width: 100%;
}
</style>
</head>
<body>
<div id="myGrid" class="ag-theme-alpine"></div>
<script src="https://cdn.jsdelivr.net/npm/ag-grid-community/dist/ag-grid-community.min.js"></script>
<script>
// 定义列
const columnDefs = [
{ headerName: "运动员", field: "athlete", width: 150 },
{ headerName: "年龄", field: "age", width: 90 },
{ headerName: "国家", field: "country", width: 120 },
{ headerName: "年份", field: "year", width: 90 },
{ headerName: "日期", field: "date", width: 110 },
{ headerName: "运动项目", field: "sport", width: 110 },
{ headerName: "金牌", field: "gold", width: 100 },
{ headerName: "银牌", field: "silver", width: 100 },
{ headerName: "铜牌", field: "bronze", width: 100 },
{ headerName: "总计", field: "total", width: 100 }
];
// 定义行数据
const rowData = [
{ athlete: "Michael Phelps", age: 23, country: "United States", year: 2008, date: "24/08/2008", sport: "Swimming", gold: 8, silver: 0, bronze: 0, total: 8 },
{ athlete: "Michael Phelps", age: 19, country: "United States", year: 2004, date: "29/08/2004", sport: "Swimming", gold: 6, silver: 0, bronze: 2, total: 8 },
{ athlete: "Michael Phelps", age: 27, country: "United States", year: 2012, date: "12/08/2012", sport: "Swimming", gold: 4, silver: 2, bronze: 0, total: 6 }
];
// 网格选项
const gridOptions = {
defaultColDef: {
sortable: true,
filter: true
},
columnDefs: columnDefs,
rowData: rowData
};
// 创建网格
const eGridDiv = document.querySelector('#myGrid');
new agGrid.Grid(eGridDiv, gridOptions);
</script>
</body>
</html>
💡 老曹讲解: 这是一个完整的 HTML + JS 示例:
- headerName:列标题
- field:对应数据字段名
- width:列宽
- defaultColDef:所有列的默认配置
- 配置了默认启用排序和过滤
✅2.2.2 React 版本
import React, { useState } from 'react';
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';
const GridExample = () => {
const [rowData] = useState([
{ athlete: "Michael Phelps", age: 23, country: "United States", year: 2008, date: "24/08/2008", sport: "Swimming", gold: 8, silver: 0, bronze: 0, total: 8 },
{ athlete: "Michael Phelps", age: 19, country: "United States", year: 2004, date: "29/08/2004", sport: "Swimming", gold: 6, silver: 0, bronze: 2, total: 8 },
{ athlete: "Michael Phelps", age: 27, country: "United States", year: 2012, date: "12/08/2012", sport: "Swimming", gold: 4, silver: 2, bronze: 0, total: 6 }
]);
const [columnDefs] = useState([
{ headerName: "运动员", field: "athlete", width: 150 },
{ headerName: "年龄", field: "age", width: 90 },
{ headerName: "国家", field: "country", width: 120 },
{ headerName: "年份", field: "year", width: 90 },
{ headerName: "日期", field: "date", width: 110 },
{ headerName: "运动项目", field: "sport", width: 110 },
{ headerName: "金牌", field: "gold", width: 100 },
{ headerName: "银牌", field: "silver", width: 100 },
{ headerName: "铜牌", field: "bronze", width: 100 },
{ headerName: "总计", field: "total", width: 100 }
]);
return (
<div className="ag-theme-alpine" style={{ height: 500, width: '100%' }}>
<AgGridReact
rowData={rowData}
columnDefs={columnDefs}
defaultColDef={{
sortable: true,
filter: true
}}
/>
</div>
);
};
export default GridExample;
💡 老曹讲解: React 版本的实现要点:
- rowData:行数据
- columnDefs:列定义
- defaultColDef:默认列配置
🎯 第二章:核心概念详解
📊 3.1 Grid Options(网格选项)
const gridOptions = {
// 列定义
columnDefs: columnDefs,
// 行数据
rowData: rowData,
// 默认列定义
defaultColDef: {
sortable: true,
filter: true,
resizable: true
},
// 行选择
rowSelection: 'multiple',
// 分页
pagination: true,
paginationPageSize: 10,
// 主题
theme: 'ag-theme-alpine'
};
💡 老曹讲解: gridOptions 是 AG Grid 的核心配置对象,常用属性:
- columnDefs:列定义数组
- rowData:表格数据
- defaultColDef:所有列的默认配置
- rowSelection:行选择模式(‘single’ 或 ‘multiple’)
- 分页相关:
- pagination:启用分页
- paginationPageSize:每页行数
- theme:主题类名(需配合对应 CSS)
📋 3.2 Column Definitions(列定义)
const columnDefs = [
{
headerName: "姓名",
field: "name",
width: 150,
sortable: true,
filter: true,
editable: true
},
{
headerName: "年龄",
field: "age",
width: 100,
type: 'numericColumn',
filter: 'agNumberColumnFilter'
},
{
headerName: "入职日期",
field: "startDate",
width: 150,
valueFormatter: (params) => {
return new Date(params.value).toLocaleDateString();
}
}
];
💡 老曹讲解: 列定义对象的常用属性:
- headerName:列标题文本
- field:对应数据字段
- width:列宽
- sortable:启用排序
- filter:启用过滤(可指定过滤器类型)
- editable:允许单元格编辑
- type:列类型(如 numericColumn 会右对齐数字)
- valueFormatter:格式化显示值(这里将日期格式化为本地字符串)
📦 3.3 Row Data(行数据)
const rowData = [
{ id: 1, name: "张三", age: 25, department: "技术部", startDate: "2020-01-15" },
{ id: 2, name: "李四", age: 30, department: "销售部", startDate: "2019-03-20" },
{ id: 3, name: "王五", age: 28, department: "人事部", startDate: "2021-07-10" }
];
💡 老曹讲解: 行数据格式要求:
- 必须是对象数组
- 每个对象代表一行数据
- 对象属性名需要与 columnDefs 中的 field 匹配
- 可以包含额外字段(即使不显示)
🎨 第三章:基础功能实现
🔀 4.1 排序功能
✅4.1.1 基础排序
const columnDefs = [
{
headerName: "姓名",
field: "name",
sortable: true
},
{
headerName: "年龄",
field: "age",
sortable: true
}
];
💡 老曹讲解: 通过设置 sortable: true 启用排序,用户可以点击列头进行排序
✅4.1.2 自定义排序
const columnDefs = [
{
headerName: "姓名",
field: "name",
sortable: true,
comparator: (valueA, valueB, nodeA, nodeB, isDescending) => {
// 自定义排序逻辑
if (valueA === valueB) return 0;
return (valueA > valueB) ? 1 : –1;
}
}
];
💡 老曹讲解: comparator 函数参数说明:
- valueA, valueB:要比较的两个值
- nodeA, nodeB:对应的行节点对象
- isDescending:是否降序 返回值:
- 负数:valueA 排在前面
- 正数:valueB 排在前面
- 0:相等
🔍 4.2 过滤功能
✅4.2.1 文本过滤
const columnDefs = [
{
headerName: "姓名",
field: "name",
filter: 'agTextColumnFilter',
filterParams: {
buttons: ['reset', 'apply'],
closeOnApply: true
}
}
];
💡 老曹讲解: 文本过滤器配置:
- filter: 'agTextColumnFilter':指定使用文本过滤器
- filterParams:过滤器参数
- buttons:显示重置和应用按钮
- closeOnApply:应用后自动关闭过滤器弹窗
✅4.2.2 数字过滤
const columnDefs = [
{
headerName: "年龄",
field: "age",
filter: 'agNumberColumnFilter',
filterParams: {
filterOptions: ['equals', 'notEqual', 'lessThan', 'greaterThan'],
buttons: ['apply', 'reset'],
closeOnApply: true
}
}
];
💡 老曹讲解: 数字过滤器特有配置:
- filterOptions:指定可用的过滤条件类型 其他参数与文本过滤器类似
📄 4.3 分页功能
const gridOptions = {
pagination: true,
paginationPageSize: 10,
paginationPageSizeSelector: [5, 10, 20, 50],
suppressPaginationPanel: false
};
💡 老曹讲解: 分页配置选项:
- pagination:启用分页
- paginationPageSize:默认每页行数
- paginationPageSizeSelector:可选的每页行数选项
- suppressPaginationPanel:是否隐藏分页控制栏(false 表示显示)
✏️ 第四章:编辑功能详解
📝 5.1 单元格编辑
✅5.1.1 启用编辑
const columnDefs = [
{
headerName: "姓名",
field: "name",
editable: true
},
{
headerName: "年龄",
field: "age",
editable: true,
cellEditor: 'agNumberCellEditor'
}
];
const gridOptions = {
defaultColDef: {
editable: true
},
onCellValueChanged: (event) => {
console.log('单元格值已更改:', event);
}
};
💡 老曹讲解: 编辑功能配置:
- editable: true:启用编辑
- cellEditor:指定编辑器类型(这里使用数字输入框)
- onCellValueChanged:单元格值改变时触发
- event 对象包含:数据、列、行节点等信息
✅5.1.2 自定义编辑器
class CustomEditor {
init(params) {
this.value = params.value;
this.input = document.createElement('input');
this.input.type = 'text';
this.input.value = this.value;
}
getValue() {
return this.input.value;
}
getGui() {
return this.input;
}
afterGuiAttached() {
this.input.focus();
}
}
const columnDefs = [
{
headerName: "自定义编辑",
field: "customField",
cellEditor: CustomEditor,
editable: true
}
];
💡 老曹讲解: 自定义编辑器需要实现以下方法:
📊 第五章:分组与聚合功能
📁 6.1 行分组
const columnDefs = [
{
headerName: "国家",
field: "country",
rowGroup: true,
hide: true
},
{
headerName: "运动员",
field: "athlete"
},
{
headerName: "金牌",
field: "gold",
aggFunc: 'sum'
}
];
const gridOptions = {
groupDisplayType: 'groupRows',
groupDefaultExpanded: 1,
suppressAggFuncInHeader: true
};
💡 老曹讲解: 行分组配置:
- rowGroup: true:指定该列为分组列
- hide: true:通常隐藏分组列(因为会显示在分组行中)
- aggFunc:指定聚合函数(这里对金牌数求和)
- groupDisplayType:分组显示方式(‘groupRows’ 表示显示展开的分组行)
- groupDefaultExpanded:默认展开层级(1 表示展开第一级)
- suppressAggFuncInHeader:是否在列头隐藏聚合函数名称
📈 6.2 数据聚合
const columnDefs = [
{
headerName: "金牌",
field: "gold",
aggFunc: 'sum'
},
{
headerName: "银牌",
field: "silver",
aggFunc: 'sum'
},
{
headerName: "总计",
field: "total",
aggFunc: 'sum'
}
];
// 自定义聚合函数
const customAggFunc = (values) => {
return values.reduce((sum, value) => sum + value, 0);
};
💡 老曹讲解: 聚合功能配置:
- sum:求和
- avg:平均值
- min/max:最小/最大值
- count:计数
- 接收参数 values:当前分组所有值数组
- 需要返回聚合结果
- 示例中的 reduce 实现了求和功能
- 通常用于分组行或底部合计行
⛄ 第六章:自定义渲染与样式
🖌️ 7.1 自定义单元格渲染器
class CustomCellRenderer {
// 初始化方法,params包含单元格数据和配置
init(params) {
// 创建DOM元素容器
this.eGui = document.createElement('div');
// 设置自定义HTML内容,这里将文本显示为蓝色加粗
this.eGui.innerHTML = `<span style="color: blue; font-weight: bold;">${params.value}</span>`;
}
// 返回创建的DOM元素
getGui() {
return this.eGui;
}
}
// 列定义中使用自定义渲染器
const columnDefs = [
{
headerName: "自定义渲染", // 列标题
field: "name", // 数据字段名
cellRenderer: CustomCellRenderer // 指定自定义渲染器
}
];
💡 老曹讲解:
🎨 7.2 条件样式
// 列定义中使用条件样式
const columnDefs = [
{
headerName: "年龄",
field: "age",
// 单元格样式回调函数
cellStyle: (params) => {
// 根据值返回不同的样式对象
if (params.value > 30) {
return { backgroundColor: 'lightcoral' }; // 大于30显示浅红色背景
} else if (params.value < 25) {
return { backgroundColor: 'lightgreen' }; // 小于25显示浅绿色背景
}
return null; // 其他情况使用默认样式
}
}
];
💡 老曹讲解::
🎭 7.3 主题定制
/* 自定义主题样式 */
.ag-theme-custom {
/* 基础颜色 */
–ag-foreground-color: #333; /* 文字颜色 */
–ag-background-color: #fff; /* 背景颜色 */
/* 表头样式 */
–ag-header-foreground-color: #fff; /* 表头文字颜色 */
–ag-header-background-color: #37474f; /* 表头背景颜色 */
/* 行样式 */
–ag-odd-row-background-color: #f5f5f5; /* 奇数行背景 */
/* 边框样式 */
–ag-border-color: #ccc; /* 边框颜色 */
}
💡 老曹讲解:
- 定义CSS变量
- 应用ag-theme-custom类到网格容器
第七章:性能优化技巧
🚀 8.1 虚拟滚动
const gridOptions = {
// 指定行模型类型(客户端渲染)
rowModelType: 'clientSide',
// 设置行缓冲区大小(预加载行数)
rowBuffer: 10,
// 确保启用行虚拟化(默认true)
suppressRowVirtualisation: false
};
💡 老曹讲解:
📦 8.2 数据更新优化
// 批量更新数据(推荐方式)
const updateData = () => {
gridOptions.api.applyTransaction({
update: updatedRows, // 要更新的行数组
add: newRows, // 要添加的行数组
remove: deletedRows // 要删除的行数组
});
};
// 部分单元格刷新(更细粒度控制)
const refreshCells = () => {
gridOptions.api.refreshCells({
rowNodes: [rowNode], // 要刷新的行节点数组
columns: ['name', 'age'] // 要刷新的列字段数组
});
};
💡 老曹讲解:
⚙️ 8.3 内存管理
const gridOptions = {
// 网格就绪回调
onGridReady: (params) => {
// 添加窗口大小变化监听
window.addEventListener('resize', function() {
setTimeout(function() {
params.api.sizeColumnsToFit(); // 调整列宽适应容器
})
});
},
// 网格销毁回调
onGridDestroyed: () => {
console.log('Grid destroyed');
// 这里可以添加清理逻辑
}
};
// 手动销毁网格(在组件卸载时调用)
const destroyGrid = () => {
if (gridOptions.api) {
gridOptions.api.destroy();
}
};
💡 老曹讲解:
第八章:国际化支持
🌍 9.1 多语言配置
// 中文本地化配置
const localeText = {
// 分页控件
page: '页',
more: '更多',
to: '到',
of: '共',
next: '下一页',
last: '最后一页',
first: '第一页',
previous: '上一页',
// 加载状态
loadingOoo: '加载中…',
// 空状态
noRowsToShow: '暂无数据',
// 过滤控件
filterOoo: '过滤…',
equals: '等于',
notEqual: '不等于',
lessThan: '小于',
greaterThan: '大于'
};
// 应用本地化配置
const gridOptions = {
localeText: localeText
};
💡 老曹讲解:
🌐 9.2 动态切换语言
// 语言切换函数
const switchLanguage = (language) => {
let localeText;
switch(language) {
case 'zh':
localeText = { /* 中文配置 */ };
break;
case 'en':
localeText = { /* 英文配置 */ };
break;
case 'ja':
localeText = { /* 日文配置 */ };
break;
default:
localeText = {};
}
// 应用新的语言配置
if (gridOptions.api) {
gridOptions.api.setGridOption('localeText', localeText);
// 强制刷新网格以应用新文本
gridOptions.api.redrawRows();
}
};
💡 老曹讲解:
第九章:事件处理与API操作
🎯 10.1 事件监听
const gridOptions = {
// 单元格点击事件
onCellClicked: (event) => {
console.log('单元格被点击:', {
column: event.column.getColId(),
value: event.value,
rowData: event.data
});
},
// 行选择事件
onSelectionChanged: (event) => {
const selectedRows = event.api.getSelectedRows();
console.log('选中的行:', selectedRows);
},
// 排序变化事件
onSortChanged: (event) => {
const sortModel = event.api.getSortModel();
console.log('当前排序:', sortModel);
},
// 过滤变化事件
onFilterChanged: (event) => {
const filterModel = event.api.getFilterModel();
console.log('当前过滤条件:', filterModel);
}
};
💡 老曹讲解:
- 单元格事件:onCellClicked, onCellDoubleClicked
- 行事件:onRowSelected, onRowClicked
- 数据事件:onRowDataUpdated, onFilterChanged
🔧 10.2 API 操作
// 获取API实例(通常在事件回调中已提供)
let gridApi;
// 数据操作
function manipulateData() {
// 设置新数据
gridApi.setRowData(newDataArray);
// 批量更新
gridApi.applyTransaction({
add: [{id: 1, name: 'New Item'}],
update: [{id: 2, name: 'Updated Item'}]
});
// 获取选中行
const selected = gridApi.getSelectedRows();
}
// 列操作
function manipulateColumns() {
// 自动调整所有列宽
gridApi.autoSizeAllColumns();
// 隐藏列
gridApi.setColumnVisible('age', false);
// 获取列定义
const colDefs = gridApi.getColumnDefs();
}
// 视图操作
function manipulateView() {
// 聚焦到第一行
const firstRow = gridApi.getDisplayedRowAtIndex(0);
gridApi.setFocusedCell(0, 'name');
// 滚动到指定行
gridApi.ensureIndexVisible(100);
}
💡 老曹讲解:
- 数据操作:setRowData, applyTransaction
- 选择操作:getSelectedRows, deselectAll
- 视图操作:sizeColumnsToFit, scrollTo
- 列操作:setColumnDefs, autoSizeColumn
第十章:最佳实践与常见问题
💡 11.1 最佳实践
✅11.1.1 性能优化建议
const performanceOptions = {
// 列定义优化
defaultColDef: {
width: 120, // 合理默认宽度
minWidth: 50, // 最小宽度限制
maxWidth: 500, // 最大宽度限制
resizable: true, // 允许调整大小
sortable: true // 允许排序
},
// 渲染优化
suppressCellSelection: true, // 禁用单元格文本选择
ensureDomOrder: true, // 保持DOM顺序(对SEO友好)
// 大数据集优化
rowModelType: 'infinite', // 无限滚动模式
cacheBlockSize: 100, // 每个缓存块大小
maxBlocksInCache: 2 // 最大缓存块数
};
💡 老曹讲解:
✅11.1.2 代码组织建议
// 推荐的项目结构
src/
├── components/
│ ├── Grid/
│ │ ├── Grid.jsx # 主组件
│ │ ├── gridConfig.js # 配置分离
│ │ ├── gridStyles.css # 样式
│ │ └── GridUtils.js # 工具函数
├── types/ # TypeScript类型定义
│ └── gridTypes.ts
└── assets/ # 静态资源
└── locales/ # 语言包
💡 老曹讲解:
❓ 11.2 常见问题解决
✅11.2.1 表格不显示
// 调试步骤
function debugGridNotShowing() {
// 1. 检查容器尺寸
const container = document.getElementById('myGrid');
console.log('Container dimensions:', container.offsetWidth, container.offsetHeight);
// 2. 验证样式引入
if (!document.querySelector('.ag-theme-alpine')) {
console.error('AG Grid theme CSS not loaded');
}
// 3. 检查数据加载
if (!gridOptions.rowData || gridOptions.rowData.length === 0) {
console.warn('No row data provided');
}
}
❗ 常见原因:
✅11.2.2 数据不更新
// 正确的数据更新模式
function safeUpdateData(newData) {
if (!gridOptions.api) {
console.error('Grid API not available');
return;
}
// 使用防抖处理高频更新
if (this.updateTimeout) {
clearTimeout(this.updateTimeout);
}
this.updateTimeout = setTimeout(() => {
gridOptions.api.setRowData([…newData]); // 创建新数组避免引用问题
}, 100);
}
❗ 常见原因:
完整示例代码参考AG Grid官方示例库。
🎯 总结与展望
📚 12.1 核心知识点回顾
通过本教程,我们系统学习了 AG Grid 的以下核心内容:
🚀 12.2 进阶学习方向
✅12.2.1 企业版功能
// 启用企业版功能
import 'ag-grid-enterprise';
const enterpriseFeatures = {
// Excel 导出
enableCellTextSelection: true,
// 高级过滤
enableCharts: true,
// 交叉表
pivotMode: true
};
✅12.2.2 服务器端数据模型
const serverSideOptions = {
rowModelType: 'serverSide',
serverSideDatasource: {
getRows: (params) => {
// 从服务器获取数据
fetch('/api/data', {
method: 'POST',
body: JSON.stringify(params.request)
})
.then(response => response.json())
.then(data => {
params.successCallback(data.rows, data.lastRow);
});
}
}
};
🎯 12.3 实际应用建议
🏋️ 通过系统学习和实践,老曹相信您已经掌握了 AG Grid 的核心技能,可以在实际项目中灵活运用这个强大的数据表格组件。记住,实践是最好的老师,建议您在实际项目中多加练习,不断提升技能水平。
评论前必须登录!
注册