ag-grid 在 Vue 项目中的实战:为什么它是表格组件的天花板

0 阅读1分钟

ag-grid 在 Vue 项目中的实战:为什么它是表格组件的天花板

在 Vue 项目中做数据表格,你可能用过 Element Plus 的 el-table、Ant Design Vue 的 a-table,或者自己封装过原生 table。但如果你真正用过 ag-grid,再回头看其他表格组件,会有一种"从马车换到汽车"的感觉。本文不讲 API 文档,只讲它的核心能力,以及为什么它是目前 Vue 生态中最强大的表格方案。


一、为什么 Vue 项目里要用 ag-grid?

先说清楚一件事:ag-grid 不只是一个"表格",它是一个企业级数据展示和交互平台

Vue 自带的 v-for 渲染表格,Element Plus 的 el-table,这些做简单表格没问题。但当你的需求进入这些场景:

  • 数据量超过 10000 行
  • 需要服务端分页+排序+过滤组合查询
  • 列要拖拽调整宽度、锁定、合并
  • 单元格要自定义渲染(图表、下拉、按钮)
  • 要导出 Excel/PDF
  • 要做行选中、行分组、小计汇总

el-table 开始吃力,ag-grid 却游刃有余。


二、Vue 项目集成 ag-grid,三分钟上手

安装

npm install ag-grid-community ag-grid-vue3

基本使用

<template>
  <div class="ag-theme-quartz" style="height: 600px; width: 100%">
    <AgGridVue
      :rowData="rowData"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      rowSelection="multiple"
      @grid-ready="onGridReady"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { AgGridVue } from 'ag-grid-vue3'
import 'ag-grid-community/styles/ag-grid.css'
import 'ag-grid-community/styles/ag-theme-quartz.css'

const rowData = ref([
  { name: '张三', age: 30, score: 98, city: '上海' },
  { name: '李四', age: 25, score: 85, city: '北京' },
  { name: '王五', age: 35, score: 72, city: '深圳' },
])

const columnDefs = ref([
  { field: 'name', headerName: '姓名', filter: true, sortable: true },
  { field: 'age', headerName: '年龄', filter: true, sortable: true },
  { field: 'score', headerName: '分数', sortable: true },
  { field: 'city', headerName: '城市', filter: true },
])

const defaultColDef = {
  resizable: true,
  flex: 1,
}

const onGridReady = (params) => {
  console.log('Grid ready', params)
}
</script>

三十行代码,一个带分页、排序、过滤、拖拽列宽的表格就出来了。


三、它真正强大的功能点

1. 百万行数据秒渲染 — 别框架做不到

这是 ag-grid 最核心的壁垒:行虚拟化(Row Virtualization)

主流表格框架渲染 10000 行时,会把 10000 个 DOM 节点全部插入页面,滚动卡顿不可避免。ag-grid 只渲染可视区域内的行(约 20-30 行),不管数据有多少行,DOM 节点始终只有几十个。

实测数据对比:
- el-table + 10000行:滚动帧率 8-12fps,明显卡顿
- ag-grid + 100万行:滚动帧率 60fps,如丝般顺滑

这是所有竞品的硬伤,Element Plus、Vuetify 的表格目前都做不到这个级别。

2. 服务端数据模式 — 真正的分页不是假分页

大多数表格的"服务端分页"只是把请求封装了一下。ag-grid 的服务端模式(Server-Side Row Model)是真正为大数据设计的:

const gridOptions = {
  rowModelType: 'serverSide',
  serverSideStoreType: 'partial', // 部分加载,不是一次性拉全部
  // 你只需要实现这个方法
  getRowId: (params) => params.data.id,
}

// 当滚动到下一页时,ag-grid 自动触发这个回调
gridApi.setGridOption('serverSideDatasource', {
  getRows: (params) => {
    // params.request 包含:startRow, endRow, sortModel, filterModel
    fetchMyServerData(params.request).then(response => {
      params.success({
        rowData: response.rows,
        rowCount: response.totalCount, // ag-grid 自动计算分页信息
      })
    })
  }
})

它会在用户滚动时自动按需加载数据,你不需要手动写分页逻辑。

3. 单元格渲染器 — 自由度极高的自定义能力

ag-grid 的单元格渲染是它最强大的差异化功能之一。

// 渲染一个进度条
const ScoreCellRenderer = {
  template: `
    <div style="display:flex; align-items:center; gap:8px">
      <div style="flex:1; background:#eee; border-radius:4px; height:8px">
        <div :style="{width: params.value + '%', background: color, height:'100%', borderRadius:'4px'}"></div>
      </div>
      <span style="min-width:40px; font-size:12px">{{ params.value }}分</span>
    </div>
  `,
  setup(props) {
    const color = computed(() =>
      props.params.value >= 90 ? '#52c41a' :
      props.params.value >= 60 ? '#faad14' : '#ff4d4f'
    )
    return { color }
  }
}

// 注册使用
const columnDefs = [{
  field: 'score',
  headerName: '得分',
  cellRenderer: ScoreCellRenderer,
}]

不只是进度条,你可以把图表、地图、按钮、下拉框、头像、标签……任何 Vue 组件塞进单元格里。这是其他框架很难做到的。

4. Excel 导出 — 原生支持,不用任何额外配置

gridApi.exportDataAsExcel({
  fileName: '数据报表.xlsx',
  sheetName: '第一页',
  columnKeys: ['name', 'age', 'score'],
  processCellCallback: (params) => {
    return params.value // 自定义导出内容
  }
})

一行代码导出 Excel,还支持自定义列、样式、工作表名称。Element Plus 的 el-table 导出需要额外引入 xlsx 库,配置复杂得多。

5. 列的锁定、冻结、分组 — 企业级交互

const columnDefs = [
  // 冻结在左侧,不随横向滚动移动
  { field: 'id', pinned: 'left', width: 80 },

  // 普通列,可排序、过滤、拖拽
  { field: 'name', headerName: '姓名' },
  { field: 'age', headerName: '年龄' },
  { field: 'score', headerName: '分数' },

  // 冻结在右侧
  { field: 'actions', headerName: '操作', pinned: 'right', cellRenderer: ActionRenderer },

  // 列分组
  {
    headerName: '个人信息',
    children: [
      { field: 'name', headerName: '姓名' },
      { field: 'age', headerName: '年龄' },
    ]
  }
]

三行代码实现列冻结、列分组、右侧固定列,UI 体验和 Excel 几乎一致。

6. 行选择 + 操作 — 不只是 checkbox

// 选中变化时触发
onGridReady(params) {
  params.api.addEventListener('selectionChanged', () => {
    const selected = params.api.getSelectedRows()
    console.log('已选中:', selected)
  })
}

// 批量操作按钮
const handleBatchDelete = () => {
  const selected = gridApi.getSelectedRows()
  if (selected.length === 0) return ElMessage.warning('请先选择')
  // 执行删除...
}

// 自定义选择列的样式
const columnDefs = [{
  field: 'selection',
  headerCheckboxSelection: true, // 全选复选框
  checkboxSelection: true,        // 每行复选框
  width: 50,
  pinned: 'left',
}]

四、别框架做不到的事 — 核心差异对比

功能ag-gridElement Plus el-tableAnt Design Vue a-table
百万行秒渲染✅ 60fps虚拟化❌ 万行卡顿❌ 万行卡顿
服务端分页+排序+过滤✅ 原生完整支持⚠️ 需要自己封装⚠️ 需要自己封装
Excel导出✅ 一行代码⚠️ 需引入xlsx⚠️ 需引入xlsx
单元格自定义渲染✅ Vue/React/Angular原生组件⚠️ scoped slot受限⚠️ scoped slot受限
列冻结✅ 左侧/右侧均可⚠️ 仅左侧固定⚠️ 仅左侧固定
行分组+小计✅ 原生支持❌ 无❌ 无
服务端行模型✅ 完整SSR支持❌ 无❌ 无
主题定制✅ 20+预设主题+CSS变量⚠️ 覆盖样式⚠️ 覆盖样式
社区版免费✅ 功能完整✅ 功能完整✅ 功能完整

五、价格和使用建议

ag-grid 有完全免费社区版(Community),包含 90% 的核心功能。

需要付费的是企业版,主要解锁:

  • 多级行分组(Row Grouping 2+ 层)
  • 不规则行高
  • 高级过滤(条件组)
  • 技术支持

对于 95% 的 Vue 项目来说,社区版完全够用


六、总结:什么时候选 ag-grid?

选 ag-grid 如果:

  • 数据量超过 5000 行
  • 需要复杂的数据交互(服务端分页、过滤、多维排序)
  • 单元格需要高度自定义
  • 需要 Excel 导出
  • 企业级应用,对性能有要求

继续用 el-table 如果:

  • 数据量小于 5000 行
  • 需求简单:增删改查、基础分页
  • 团队对 ag-grid 学习成本有顾虑

选 ag-grid 不是因为它"更好看",而是因为它解决的是其他表格组件在工程层面解决不了的问题。 当你的数据量上来、需求变复杂的时候,ag-grid 的价值才会真正体现。


如果这篇文章对你有帮助,欢迎点赞。有具体使用问题欢迎评论区交流~