vxe-table 进阶:同时使用 formatter 与 cell-render 实现格式化与样式定制

在开发表格组件时,我们经常需要完成两个任务:格式化原始数据(如数字千分位、日期格式化)和自定义单元格样式(如根据数值显示不同颜色、添加后缀)。

vxe-table 提供了 formatter 和 cell-render 两个配置项,二者可以组合使用,让数据逻辑与展示样式分离,达到更灵活的配置效果。

本文通过一个金额列的示例,演示如何同时使用 formatter 对数字添加千分位分隔符,再通过自定义渲染器 cell-render 将格式化后的内容渲染为红色并加上"元"后缀。

效果预览

  • 金额列会显示为:
    • 原始数据:1000 → 展示 1,000元(红色)
    • 原始数据:254400000 → 展示 254,400,000元(红色)

代码

定义渲染器

1.1 首先需要使用 VxeUI.renderer.add 注册一个渲染器,渲染器内部引用一个 Vue 组件(DemoCellStyle.vue),该组件负责最终单元格的样式呈现。

注册渲染器 (renderer.js)

javascript 复制代码
import { VxeUI } from 'vxe-pc-ui'

import DemoCellStyle from './DemoCellStyle.vue'

// 创建单元格样式渲染器
VxeUI.renderer.add('MyTableCellStyle', {
  // 默认显示模板
  renderTableDefault(renderOpts, renderParams) {
    return <DemoCellStyle render-params={renderParams} />
  }
})

2.1 编写渲染器组件 DemoCellStyle.vue

该组件通过 renderParams 获取当前单元格的上下文,并调用 $table.getCellLabel(row, column) 来获取 经过 formatter 处理后的文本内容,然后将其包裹在自定义样式中。

html 复制代码
<template>
  <span style="color: red">{{ cellLabel }}元</span>
</template>

<script setup>
import { ref, computed } from 'vue'

const props = defineProps({
  renderParams: {
    type: Object,
    default: () => ({})
  }
})

const cellLabel = computed(() => {
  const { renderParams } = props
  const { $table, row, column } = renderParams
  if ($table && row && column) {
    return $table.getCellLabel(row, column)
  }
  return ''
})
</script>
  • 关键点:$table.getCellLabel() 会优先执行列上配置的 formatter 函数,拿到格式化后的字符串,然后传给自定义渲染器。这样我们就实现了 formatter 负责数据格式化,cell-render 负责样式展示 的完美分工。

使用

  • 在 vxe-grid 的列定义中:
    • formatter:对原始数值添加千分位分隔符(例如 1000 → 1,000)。
    • cellRender:指定使用上面注册的渲染器 'MyTableCellStyle',该渲染器会将格式化后的文本加上"元"后缀并显示为红色。
html 复制代码
<template>
  <div>
    <vxe-grid v-bind="gridOptions"></vxe-grid>
  </div>
</template>

<script lang="jsx" setup>
import { reactive } from 'vue'
import XEUtils from 'xe-utils'
const gridOptions = reactive({
  border: true,
  height: 300,
  columns: [
    { type: 'seq', width: 50 },
    { field: 'name', title: 'Name' },
    { field: 'sex', title: 'Sex' },
    {
      field: 'amount',
      title: 'Amount',
      // 数据格式化:千分位分隔
      formatter({ cellValue }) {
        return XEUtils.commafy(cellValue)
      },
      // 式渲染:使用自定义渲染器
      cellRender: {
        name: 'MyTableCellStyle'
      }
    }
  ],
  data: [
    { id: 10001, name: 'Test1', sex: 'Man', age: 28, amount: 1000 },
    { id: 10002, name: 'Test2', sex: 'Women', age: 22, amount: 254400000 },
    { id: 10003, name: 'Test3', sex: 'Man', age: 32, amount: 999954 },
    { id: 10004, name: 'Test4', sex: 'Women', age: 23, amount: 10000000 }
  ]
})
</script>

原理说明

配置项 职责 执行顺序
formatter 将原始数据转换为展示用的纯文本(如数字千分位、日期格式化) 先执行
cellRender 接管整个单元格的渲染,可自定义任意 VNode 或组件 后执行,并可获取 formatter 的结果

两者组合时,cellRender 内部通过 $table.getCellLabel(row, column) 拿到已经经过 formatter 处理的文本,然后进行二次包装(加后缀、改颜色、加图标等)。这样既复用了 formatter 的格式化能力,又保留了渲染器的高度灵活性。

说明

  • cellRender 会完全接管单元格内容:一旦配置了 cellRender,默认的文本渲染就会被覆盖,所以必须在自定义组件内显式调用 getCellLabel 来呈现格式化后的文本。
  • 性能考虑:如果只是简单的样式修改(如颜色、字体),也可以直接使用 cellClassName 或 style 回调;但当需要组合复杂逻辑(如根据多列值、动态添加组件)时,cellRender 更加强大。
  • 扩展性:通过注册不同的渲染器,可以在不同列或不同项目中复用样式逻辑。

这种模式非常适合需要统一格式化数据,但又希望在不同场景下呈现不同样式的业务需求(如金额、状态标签、进度条等)。

https://vxetable.cn

相关推荐
7yue1 小时前
我用 AI 把 Learn Claude Code 改写成了 TypeScript + 代数效应版本
前端
云宝大王1 小时前
JavaScript 异步编程:从回调到探索 Promise的秘密
前端·javascript
用户059540174461 小时前
用LangChain+FastAPI构建私有知识库踩坑实录:这3个问题让我排查了整整8小时
前端·css
Momo__1 小时前
CSS View Transitions 新语法:sibling-index() + ident(),千级元素命名难题的终局方案
前端·css
前端张三1 小时前
ant design vue table 使用虚拟滚动
前端·javascript·vue.js
木子雨廷1 小时前
Flutter 内存管理实战:从 GC 原理到 DevTools 泄漏排查
前端·flutter
Rkgua1 小时前
TS中`Function`、`CallableFunction` 和 `NewableFunction`的函数区别
前端
Asize1 小时前
重生之我在 Vibe Coding 时代当程序员:第十一课,JS底层 :变量提升真相
前端·javascript
HYCS1 小时前
用pixi.js实现fabric.js(五):事件系统
前端·javascript·canvas