Skip to content

useAgGrid Aggrid 工具

ag-grid 是世界上最好的 JavaScript 网格,但在使用时可能需要进一步封装,这里提供轻量的工具,方便使用。

未使用状态(适应内容宽度)

如果内容过多将导致横向滚动非常长。

<script lang="ts" setup>
import { ref } from 'vue'
import { AgGridVue } from '@ag-grid-community/vue3'
import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model'
import '@ag-grid-community/styles/ag-grid.css'
import '@ag-grid-community/styles/ag-theme-alpine.css'
const modules = [ClientSideRowModelModule]

const rowData = ref<any[]>([])

const colDefs = ref([
  { field: 'make', tooltipField: 'make', headerName: 'MAKEEEEEE' },
  { field: 'model' },
  { field: 'price', tooltipField: 'price' },
  { field: 'electric', pinned: 'right' },
])

setTimeout(() => {
  rowData.value = [
    {
      make: 'Tesla',
      model:
        'Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y',
      price: `649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950`,
      electric: true,
    },
    { make: 'Ford', model: 'F-Series', price: 33850, electric: false },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: false },
  ]
}, 100)
</script>

<template>
  <ag-grid-vue
    :modules="modules"
    :rowData="rowData"
    :columnDefs="colDefs"
    class="ag-theme-alpine"
    style="height: 300px"
    :tooltipInteraction="true"
    :tooltipShowDelay="500"
    :autoSizeStrategy="{
      type: 'fitCellContents',
    }"
  >
  </ag-grid-vue>
</template>

最大宽度

ag-grid 可以设置 defaultColDef 来限制最大宽度,但将导致无法拖宽宽度。

<script lang="ts" setup>
import { ref } from 'vue'
import { AgGridVue } from '@ag-grid-community/vue3'
import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model'
import '@ag-grid-community/styles/ag-grid.css'
import '@ag-grid-community/styles/ag-theme-alpine.css'
const modules = [ClientSideRowModelModule]

const rowData = ref<any[]>([])

const colDefs = ref([
  { field: 'make', tooltipField: 'make', headerName: 'MAKEEEEEE' },
  { field: 'model' },
  { field: 'price', tooltipField: 'price' },
  { field: 'electric', pinned: 'right' },
])

setTimeout(() => {
  rowData.value = [
    {
      make: 'Tesla',
      model:
        'Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y',
      price: `649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950`,
      electric: true,
    },
    { make: 'Ford', model: 'F-Series', price: 33850, electric: false },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: false },
  ]
}, 100)
</script>

<template>
  <ag-grid-vue
    :modules="modules"
    :rowData="rowData"
    :columnDefs="colDefs"
    class="ag-theme-alpine"
    style="height: 300px"
    :tooltipInteraction="true"
    :tooltipShowDelay="500"
    :autoSizeStrategy="{
      type: 'fitCellContents',
    }"
    :defaultColDef="{
      maxWidth: 150,
    }"
  >
  </ag-grid-vue>
</template>

使用 useAgGrid ,需要注册两个个回调方法 gridReadyfirstDataRendered,在初次加载时限制最大宽度切后续可拖动,为了更好的展示效果自动适应宽度不再使用 aggrid 的 autoSizeStrategy 配置,改为 useAgGrid 的 fitCellContents 配置项

可以看到,因为最后一列采用右固定,此时如果所有列的宽度之和不及表格宽度,会空出来一块,看起来突兀,可以设置 fitGridWidth 并且不使用最大宽度来解决,但由于用户屏幕、缩放比例的不同,导致表格整体宽度不同,对于采用 fitCellContents 还是 fitGridWidth 其实是不好把控的,这里 useAgGrid 已帮你解决,在宽度不足时自动切换为将最后一列设置 pinned: null, 宽度超出时设置回原状态。

TIP

在数据量较大时在 rowData 赋值后调用 nextTick(firstDataRendered) 而非直接在标签上绑定来减少闪烁提高视觉效果。 如果你希望最后一列占满剩余宽度可以给列配置设置 flex: 1minWidth

<script lang="ts" setup>
import { ref } from 'vue'
import { AgGridVue } from '@ag-grid-community/vue3'
import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model'
import '@ag-grid-community/styles/ag-grid.css'
import '@ag-grid-community/styles/ag-theme-alpine.css'
import { useAgGrid } from '@x-anything/hooks'
const modules = [ClientSideRowModelModule]

const rowData = ref<any[]>([])

const colDefs = ref([
  { field: 'make', tooltipField: 'make', headerName: 'MAKEEEEEE' },
  { field: 'model' },
  { field: 'price', tooltipField: 'price' },
  { field: 'electric', pinned: 'right', flex: 1, minWidth: 100 },
])

setTimeout(() => {
  rowData.value = [
    {
      make: 'Tesla',
      model:
        'Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y',
      price: `649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950`,
      electric: true,
    },
    { make: 'Ford', model: 'F-Series', price: 33850, electric: false },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: false },
  ]
}, 100)

const { gridReady, firstDataRendered } = useAgGrid({
  fitCellContents: true,
  maxWidth: 150,
})
</script>

<template>
  <ag-grid-vue
    :modules="modules"
    :rowData="rowData"
    :columnDefs="colDefs"
    class="ag-theme-alpine"
    style="height: 300px"
    :tooltipInteraction="true"
    :tooltipShowDelay="500"
    @grid-ready="gridReady"
    @first-data-rendered="firstDataRendered"
  >
  </ag-grid-vue>
</template>

断点

有时候固定列过多,在小屏幕或移动端下可活动的中间区域很小,影响操作及查看,此时我们希望不再固定列,此时可以用到断点 breakpoint,配置后表格宽度低于此数值时将不再固定任何列。你可以拖动浏览器宽度至最小查看效果。

<script lang="ts" setup>
import { ref } from 'vue'
import { AgGridVue } from '@ag-grid-community/vue3'
import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model'
import '@ag-grid-community/styles/ag-grid.css'
import '@ag-grid-community/styles/ag-theme-alpine.css'
import { useAgGrid } from '@x-anything/hooks'
const modules = [ClientSideRowModelModule]

const rowData = ref<any[]>([])

const colDefs = ref([
  {
    field: 'make',
    tooltipField: 'make',
    headerName: 'MAKEEEEEE',
    pinned: 'left',
  },
  { field: 'model' },
  { field: 'price', tooltipField: 'price' },
  { field: 'electric', pinned: 'right' },
])

setTimeout(() => {
  rowData.value = [
    {
      make: 'Tesla',
      model:
        'Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y',
      price: `649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950`,
      electric: true,
    },
    { make: 'Ford', model: 'F-Series', price: 33850, electric: false },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: false },
  ]
}, 100)

const { gridReady, firstDataRendered } = useAgGrid({
  fitCellContents: true,
  maxWidth: 150,
  breakpoint: 400,
})
</script>

<template>
  <ag-grid-vue
    :modules="modules"
    :rowData="rowData"
    :columnDefs="colDefs"
    class="ag-theme-alpine"
    style="height: 300px"
    :tooltipInteraction="true"
    :tooltipShowDelay="500"
    @grid-ready="gridReady"
    @first-data-rendered="firstDataRendered"
  >
  </ag-grid-vue>
</template>

断点时固定

也可以配置固定列在低于断点值时仍固定指定的列。拖动浏览器宽度查看效果

<script lang="ts" setup>
import { ref } from 'vue'
import { AgGridVue } from '@ag-grid-community/vue3'
import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model'
import '@ag-grid-community/styles/ag-grid.css'
import '@ag-grid-community/styles/ag-theme-alpine.css'
import { useAgGrid } from '@x-anything/hooks'
const modules = [ClientSideRowModelModule]

const rowData = ref<any[]>([])

const colDefs = ref([
  {
    field: 'make',
    tooltipField: 'make',
    headerName: 'MAKEEEEEE',
    pinned: 'left',
  },
  { field: 'model' },
  { field: 'price', tooltipField: 'price' },
  { field: 'electric', pinned: 'right' },
])

setTimeout(() => {
  rowData.value = [
    {
      make: 'Tesla',
      model:
        'Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y',
      price: `649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950`,
      electric: true,
    },
    { make: 'Ford', model: 'F-Series', price: 33850, electric: false },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: false },
  ]
}, 100)

const { gridReady, firstDataRendered } = useAgGrid({
  fitCellContents: true,
  maxWidth: 150,
  breakpoint: 400,
  pinned: ['electric'],
})
</script>

<template>
  <ag-grid-vue
    :modules="modules"
    :rowData="rowData"
    :columnDefs="colDefs"
    class="ag-theme-alpine"
    style="height: 300px"
    :tooltipInteraction="true"
    :tooltipShowDelay="500"
    @grid-ready="gridReady"
    @first-data-rendered="firstDataRendered"
  >
  </ag-grid-vue>
</template>

记录滚动条

在 vue 中我们也许会使用 keepalive 保留列表页,但返回时 ag-grid 的滚动条会回到顶部,配置 keepScroll 为 true,会在返回时将上次点击的行展示在表格中间

滚动时指定列适应内容宽度

通常,单元格内的内容是宽度是不一致的,由于虚拟滚动,初始宽度设置的是前几十条数据的宽度,在滚动到下面时如果有较长内容将显示省略号。但某些时候,我们希望内容完全展示,如内容为权限控制的不定数量的操作按钮。这时就需要在滚动后调整列的宽度,配置 autoSizeColumns 并指定哪些列需要滚动时调整。

你可以滚动查看效果,如果出现更多按钮时该列会调整宽度

<script lang="ts" setup>
import { ref } from 'vue'
import { AgGridVue } from '@ag-grid-community/vue3'
import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model'
import '@ag-grid-community/styles/ag-grid.css'
import '@ag-grid-community/styles/ag-theme-alpine.css'
import { useAgGrid } from '@x-anything/hooks'
const modules = [ClientSideRowModelModule]

const rowData = ref<any[]>([])

const colDefs = ref([
  {
    field: 'make',
    tooltipField: 'make',
    headerName: 'MAKEEEEEE',
    pinned: 'left',
  },
  { field: 'model' },
  { field: 'price', tooltipField: 'price' },
  { field: 'electric', pinned: 'right' },
])

setTimeout(() => {
  rowData.value = [
    {
      make: 'Tesla',
      model:
        'Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y Model Y',
      price: `649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950649506495064950`,
      electric: '按钮 按钮',
    },
    { make: 'Ford', model: 'F-Series', price: 33850, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    { make: 'Toyota', model: 'Corolla', price: 29600, electric: '按钮 按钮' },
    {
      make: 'Toyota',
      model: 'Corolla',
      price: 29600,
      electric: '按钮 按钮 按钮 按钮',
    },
    {
      make: 'Toyota',
      model: 'Corolla',
      price: 29600,
      electric: '按钮 按钮 按钮 按钮',
    },
    {
      make: 'Toyota',
      model: 'Corolla',
      price: 29600,
      electric: '按钮 按钮 按钮 按钮',
    },
    {
      make: 'Toyota',
      model: 'Corolla',
      price: 29600,
      electric: '按钮 按钮 按钮 按钮',
    },
    {
      make: 'Toyota',
      model: 'Corolla',
      price: 29600,
      electric: '按钮 按钮 按钮 按钮',
    },
    {
      make: 'Toyota',
      model: 'Corolla',
      price: 29600,
      electric: '按钮 按钮 按钮 按钮',
    },
    {
      make: 'Toyota',
      model: 'Corolla',
      price: 29600,
      electric: '按钮 按钮 按钮 按钮',
    },
    {
      make: 'Toyota',
      model: 'Corolla',
      price: 29600,
      electric: '按钮 按钮 按钮 按钮',
    },
    {
      make: 'Toyota',
      model: 'Corolla',
      price: 29600,
      electric: '按钮 按钮 按钮 按钮',
    },
    {
      make: 'Toyota',
      model: 'Corolla',
      price: 29600,
      electric: '按钮 按钮 按钮 按钮',
    },
  ]
}, 100)

const { gridReady, firstDataRendered } = useAgGrid({
  fitCellContents: true,
  maxWidth: 300,
  autoSizeColumns: ['electric'],
})
</script>

<template>
  <ag-grid-vue
    :modules="modules"
    :rowData="rowData"
    :columnDefs="colDefs"
    class="ag-theme-alpine"
    style="height: 300px"
    :tooltipInteraction="true"
    :tooltipShowDelay="500"
    @grid-ready="gridReady"
    @first-data-rendered="firstDataRendered"
  >
  </ag-grid-vue>
</template>