news 2026/3/7 22:05:45

从需求到实践:深入浅出 vxe-table 表格组件使用指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从需求到实践:深入浅出 vxe-table 表格组件使用指南

前言

在前端开发中,我们经常会遇到这样的需求场景:需要展示大量数据的树形结构表格,并且要在表格单元格内插入输入框、选择器、开关等可交互元素。传统的表格组件往往在面对这种复杂场景时力不从心:性能问题、功能不足、配置复杂等问题接踵而至。

这时候,vxe-table就成为了一个理想的解决方案。本文将详细介绍 vxe-table 的核心功能和使用方法,帮助大家快速上手这个强大的表格组件。


一、vxe-table 简介

1.1 什么是 vxe-table

vxe-table 是一个基于 Vue 的 PC 端表格组件,支持增删改查、虚拟滚动、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、自定义模板等强大功能。

官网地址:https://vxetable.cn

GitHub:https://github.com/x-extends/vxe-table

1.2 为什么选择 vxe-table

相比其他表格组件,vxe-table 的优势在于:

  • 性能优秀:支持虚拟滚动,可流畅展示海量数据(10万+行)
  • 功能全面:内置表单渲染、单元格编辑、树形结构等常用功能
  • 高度可定制:支持自定义渲染器、插槽、主题配置
  • 开箱即用:提供丰富的 API 和完善的文档
  • 生态完善:配套 vxe-table-plugin-* 系列插件

1.3 适用场景

  • 大数据量表格展示(虚拟滚动)
  • 树形表格/树形网格
  • 可编辑表格(单元格编辑)
  • 复杂表单渲染
  • 数据导入导出
  • 数据校验

二、快速开始

2.1 安装

使用 npm 或 yarn 安装:

# npm 安装 npm install vxe-table xe-utils # yarn 安装 yarn add vxe-table xe-utils

2.2 全局引入

main.js中引入:

import { createApp } from 'vue' import App from './App.vue' // 引入 vxe-table import VXETable from 'vxe-table' import 'vxe-table/lib/style.css' const app = createApp(App) // 全局安装 app.use(VXETable) app.mount('#app')

2.3 按需引入(推荐)

import { createApp } from 'vue' import App from './App.vue' // 按需引入 import { VXETable, // 核心 Icon, Column, Table, // 可选组件 Edit, Menu, Export, Keyboard, Validator } from 'vxe-table' import 'vxe-table/lib/style.css' const app = createApp(App) // 安装需要的模块 app.use(Icon) app.use(Column) app.use(Table) app.use(Edit) app.use(Menu) app.use(Export) app.use(Keyboard) app.use(Validator) app.mount('#app')

三、基础使用

3.1 基础表格

最简单的表格使用示例:

<template> <div> <vxe-table :data="tableData"> <vxe-column field="id" title="ID" width="80"></vxe-column> <vxe-column field="name" title="姓名" width="150"></vxe-column> <vxe-column field="age" title="年龄" width="100"></vxe-column> <vxe-column field="address" title="地址"></vxe-column> </vxe-table> </div> </template> <script setup> import { ref } from 'vue' const tableData = ref([ { id: 1, name: '张三', age: 28, address: '北京市朝阳区' }, { id: 2, name: '李四', age: 32, address: '上海市浦东新区' }, { id: 3, name: '王五', age: 25, address: '广州市天河区' } ]) </script>

3.2 树形表格

vxe-table 对树形结构有原生支持:

<template> <div> <vxe-table :data="treeData" :tree-config="{ children: 'children', expandAll: true }" border > <vxe-column field="name" title="部门名称" tree-node></vxe-column> <vxe-column field="leader" title="负责人" width="150"></vxe-column> <vxe-column field="count" title="人数" width="100"></vxe-column> </vxe-table> </div> </template> <script setup> import { ref } from 'vue' const treeData = ref([ { name: '技术部', leader: '张三', count: 15, children: [ { name: '前端组', leader: '李四', count: 8 }, { name: '后端组', leader: '王五', count: 7 } ] }, { name: '产品部', leader: '赵六', count: 10, children: [ { name: '产品设计组', leader: '钱七', count: 5 }, { name: '用户研究组', leader: '孙八', count: 5 } ] } ]) </script>

四、单元格编辑与表单元素

4.1 单元格编辑(edit-render)

这是 vxe-table 的核心功能之一,可以在单元格中渲染各种表单元素:

输入框(input)
<template> <vxe-table :data="tableData" :edit-config="{ trigger: 'click', mode: 'cell' }"> <vxe-column field="name" title="姓名" :edit-render="{ name: 'input' }"></vxe-column> <vxe-column field="age" title="年龄" :edit-render="{ name: 'input', props: { type: 'number' } }"></vxe-column> </vxe-table> </template> <script setup> import { ref } from 'vue' const tableData = ref([ { id: 1, name: '张三', age: 28 }, { id: 2, name: '李四', age: 32 } ]) </script>
下拉选择器(select)
<template> <vxe-table :data="tableData" :edit-config="{ trigger: 'click', mode: 'cell' }"> <vxe-column field="name" title="姓名"></vxe-column> <vxe-column field="status" title="状态" :edit-render="{ name: 'select', options: statusOptions }" ></vxe-column> <vxe-column field="role" title="角色" :edit-render="{ name: 'select', options: roleOptions, props: { multiple: true } }" ></vxe-column> </vxe-table> </template> <script setup> import { ref } from 'vue' const tableData = ref([ { id: 1, name: '张三', status: '1', role: ['admin'] }, { id: 2, name: '李四', status: '0', role: ['user'] } ]) const statusOptions = [ { label: '启用', value: '1' }, { label: '禁用', value: '0' } ] const roleOptions = [ { label: '管理员', value: 'admin' }, { label: '普通用户', value: 'user' }, { label: '访客', value: 'guest' } ] </script>
日期选择器(DatePicker)
<template> <vxe-table :data="tableData" :edit-config="{ trigger: 'click', mode: 'cell' }"> <vxe-column field="name" title="姓名"></vxe-column> <vxe-column field="birthday" title="生日" :edit-render="{ name: '$input', props: { type: 'date' } }" ></vxe-column> </vxe-table> </template> <script setup> import { ref } from 'vue' const tableData = ref([ { id: 1, name: '张三', birthday: '1995-05-12' }, { id: 2, name: '李四', birthday: '1992-08-23' } ]) </script>
开关(Switch)
<template> <vxe-table :data="tableData" :edit-config="{ trigger: 'click', mode: 'cell' }"> <vxe-column field="name" title="姓名"></vxe-column> <vxe-column field="enabled" title="启用状态" :edit-render="{ name: '$switch' }" ></vxe-column> </vxe-table> </template> <script setup> import { ref } from 'vue' const tableData = ref([ { id: 1, name: '张三', enabled: true }, { id: 2, name: '李四', enabled: false } ]) </script>

4.2 自定义渲染器(插槽)

对于更复杂的场景,可以使用插槽自定义渲染:

<template> <vxe-table :data="tableData" :edit-config="{ trigger: 'click', mode: 'cell' }"> <vxe-column field="name" title="姓名"></vxe-column> <vxe-column field="tags" title="标签"> <template #edit="{ row }"> <el-select v-model="row.tags" multiple placeholder="请选择标签"> <el-option label="Vue" value="vue"></el-option> <el-option label="React" value="react"></el-option> <el-option label="Angular" value="angular"></el-option> </el-select> </template> <template #default="{ row }"> <span v-for="tag in row.tags" :key="tag" class="tag">{{ tag }}</span> </template> </vxe-column> </vxe-table> </template> <script setup> import { ref } from 'vue' const tableData = ref([ { id: 1, name: '张三', tags: ['vue', 'react'] }, { id: 2, name: '李四', tags: ['angular'] } ]) </script> <style scoped> .tag { display: inline-block; padding: 2px 8px; margin-right: 5px; background: #f0f0f0; border-radius: 3px; font-size: 12px; } </style>

五、树形表格 + 可编辑完整示例

结合前面的知识点,我们来实现一个完整的树形可编辑表格:

<template> <div class="demo-container"> <vxe-toolbar> <template #buttons> <vxe-button @click="insertEvent">新增</vxe-button> <vxe-button @click="saveEvent">保存</vxe-button> <vxe-button @click="removeSelectEvent">删除选中</vxe-button> </template> </vxe-toolbar> <vxe-table ref="tableRef" border resizable :data="tableData" :tree-config="treeConfig" :edit-config="{ trigger: 'click', mode: 'cell' }" :checkbox-config="{ checkStrictly: true }" > <vxe-column type="checkbox" width="60"></vxe-column> <vxe-column type="seq" width="60" title="序号"></vxe-column> <vxe-column field="name" title="部门名称" tree-node :edit-render="{ name: 'input' }" ></vxe-column> <vxe-column field="leader" title="负责人" :edit-render="{ name: 'input' }" ></vxe-column> <vxe-column field="status" title="状态" :edit-render="{ name: 'select', options: statusOptions }" > <template #default="{ row }"> <span :class="'status-' + row.status"> {{ getStatusLabel(row.status) }} </span> </template> </vxe-column> <vxe-column field="count" title="人数" :edit-render="{ name: 'input', props: { type: 'number', min: 0 } }" ></vxe-column> <vxe-column field="enabled" title="启用" width="100" :edit-render="{ name: '$switch' }" > <template #default="{ row }"> <span>{{ row.enabled ? '是' : '否' }}</span> </template> </vxe-column> <vxe-column title="操作" width="200"> <template #default="{ row }"> <vxe-button type="text" @click="insertChildEvent(row)">添加子项</vxe-button> <vxe-button type="text" status="danger" @click="removeEvent(row)">删除</vxe-button> </template> </vxe-column> </vxe-table> </div> </template> <script setup> import { ref, reactive } from 'vue' import { VXETable } from 'vxe-table' const tableRef = ref() const tableData = ref([ { id: 1, name: '技术部', leader: '张三', status: '1', count: 15, enabled: true, children: [ { id: 11, name: '前端组', leader: '李四', status: '1', count: 8, enabled: true }, { id: 12, name: '后端组', leader: '王五', status: '1', count: 7, enabled: true } ] }, { id: 2, name: '产品部', leader: '赵六', status: '1', count: 10, enabled: true, children: [ { id: 21, name: '产品设计组', leader: '钱七', status: '0', count: 5, enabled: false }, { id: 22, name: '用户研究组', leader: '孙八', status: '1', count: 5, enabled: true } ] } ]) const treeConfig = reactive({ children: 'children', expandAll: true, reserve: true }) const statusOptions = [ { label: '启用', value: '1' }, { label: '禁用', value: '0' } ] const getStatusLabel = (status) => { const option = statusOptions.find(item => item.value === status) return option ? option.label : '' } let idCounter = 100 // 新增根节点 const insertEvent = () => { const newRow = { id: ++idCounter, name: '新部门', leader: '', status: '1', count: 0, enabled: true, children: [] } tableData.value.push(newRow) VXETable.modal.message({ content: '新增成功', status: 'success' }) } // 新增子节点 const insertChildEvent = (row) => { const newRow = { id: ++idCounter, name: '新子部门', leader: '', status: '1', count: 0, enabled: true } if (!row.children) { row.children = [] } row.children.push(newRow) VXETable.modal.message({ content: '添加子项成功', status: 'success' }) } // 删除行 const removeEvent = (row) => { VXETable.modal.confirm('确定要删除该行数据吗?').then(type => { if (type === 'confirm') { const removeRow = (list) => { for (let i = 0; i < list.length; i++) { if (list[i].id === row.id) { list.splice(i, 1) return true } if (list[i].children && removeRow(list[i].children)) { return true } } return false } removeRow(tableData.value) VXETable.modal.message({ content: '删除成功', status: 'success' }) } }) } // 删除选中 const removeSelectEvent = () => { const selectRecords = tableRef.value.getCheckboxRecords() if (selectRecords.length === 0) { VXETable.modal.message({ content: '请至少选择一条数据', status: 'warning' }) return } VXETable.modal.confirm(`确定要删除选中的 ${selectRecords.length} 条数据吗?`).then(type => { if (type === 'confirm') { selectRecords.forEach(record => removeEvent(record)) } }) } // 保存数据 const saveEvent = () => { const data = tableRef.value.getTableData().fullData console.log('保存的数据:', data) VXETable.modal.message({ content: '保存成功', status: 'success' }) // 这里可以调用 API 保存数据 } </script> <style scoped> .demo-container { padding: 20px; } .status-1 { color: #67c23a; } .status-0 { color: #f56c6c; } </style>

六、高级功能

6.1 虚拟滚动(大数据量)

当数据量达到上万条时,虚拟滚动可以保证流畅性:

<template> <vxe-table border height="600" :data="tableData" :scroll-y="{ enabled: true, gt: 100 }" > <vxe-column field="id" title="ID" width="80"></vxe-column> <vxe-column field="name" title="姓名"></vxe-column> <vxe-column field="age" title="年龄"></vxe-column> </vxe-table> </template> <script setup> import { ref } from 'vue' // 生成10万条数据 const tableData = ref( Array.from({ length: 100000 }, (_, i) => ({ id: i + 1, name: `用户${i + 1}`, age: Math.floor(Math.random() * 60) + 18 })) ) </script>

6.2 数据校验

vxe-table 支持强大的数据校验功能:

<template> <vxe-table :data="tableData" :edit-config="{ trigger: 'click', mode: 'cell' }" :edit-rules="editRules" > <vxe-column field="name" title="姓名" :edit-render="{ name: 'input' }" ></vxe-column> <vxe-column field="email" title="邮箱" :edit-render="{ name: 'input' }" ></vxe-column> <vxe-column field="age" title="年龄" :edit-render="{ name: 'input', props: { type: 'number' } }" ></vxe-column> </vxe-table> </template> <script setup> import { ref } from 'vue' const tableData = ref([ { id: 1, name: '张三', email: 'zhangsan@example.com', age: 28 } ]) const editRules = { name: [ { required: true, message: '姓名不能为空' }, { min: 2, max: 10, message: '姓名长度在 2 到 10 个字符' } ], email: [ { required: true, message: '邮箱不能为空' }, { pattern: /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/, message: '邮箱格式不正确' } ], age: [ { required: true, message: '年龄不能为空' }, { type: 'number', min: 18, max: 65, message: '年龄必须在 18 到 65 之间' } ] } </script>

6.3 导出 Excel

<template> <div> <vxe-button @click="exportExcel">导出Excel</vxe-button> <vxe-table ref="tableRef" :data="tableData"> <vxe-column field="name" title="姓名"></vxe-column> <vxe-column field="age" title="年龄"></vxe-column> </vxe-table> </div> </template> <script setup> import { ref } from 'vue' const tableRef = ref() const tableData = ref([ { name: '张三', age: 28 }, { name: '李四', age: 32 } ]) const exportExcel = () => { tableRef.value.exportData({ filename: '用户数据', type: 'xlsx' }) } </script>

七、性能优化建议

  1. 使用虚拟滚动:数据量大于 100 条时开启虚拟滚动
  2. 按需加载:只引入需要的组件和功能模块
  3. 懒加载树节点:树形数据较大时使用懒加载
  4. 避免过度渲染:合理使用show-overflow属性
  5. 分页加载:超大数据集使用分页而非一次性加载
<template> <vxe-table border height="600" show-overflow :data="tableData" :scroll-y="{ enabled: true }" :tree-config="{ lazy: true, loadMethod: loadChildrenMethod }" > <vxe-column field="name" title="名称" tree-node></vxe-column> </vxe-table> </template> <script setup> const loadChildrenMethod = ({ row }) => { // 异步加载子节点 return new Promise(resolve => { setTimeout(() => { resolve([ { name: `${row.name}-子节点1` }, { name: `${row.name}-子节点2` } ]) }, 500) }) } </script>

八、常见问题与解决方案

8.1 编辑状态不生效

问题:点击单元格没有进入编辑状态

解决:检查是否配置了:edit-config

<vxe-table :edit-config="{ trigger: 'click', mode: 'cell' }">

8.2 树形数据不显示

问题:树形结构没有展示出来

解决:确保配置了tree-configtree-node

<vxe-table :tree-config="{ children: 'children' }"> <vxe-column field="name" title="名称" tree-node></vxe-column> </vxe-table>

8.3 下拉选择器选项不显示

问题:select 渲染器的选项列表为空

解决:确保 options 格式正确,必须包含 label 和 value

const options = [ { label: '选项1', value: '1' }, // 正确 { label: '选项2', value: '2' } ]

九、总结

vxe-table 是一个功能强大、性能优秀的 Vue 表格组件,特别适合处理复杂的业务场景:

  • 支持树形结构和大数据量虚拟滚动
  • 内置丰富的表单渲染器(输入框、选择器、开关等)
  • 灵活的单元格编辑和数据校验
  • 完善的 API 和良好的扩展性

对于需要在表格中插入输入框、选择器等交互元素的场景,vxe-table 提供了开箱即用的解决方案,大大提升了开发效率。

建议大家在实际项目中根据具体需求,合理使用 vxe-table 的各项功能,同时注意性能优化,以获得最佳的用户体验。


参考资料

  • vxe-table 官方文档
  • vxe-table GitHub
  • vxe-table 示例

💡提示:本文基于 vxe-table 4.x 版本编写,如有版本差异请参考官方文档。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/5 11:34:46

Redis100篇 - Redis的GeoHash功能 实现附近的人+距离计算

文章目录Redis100篇 - Redis的GeoHash功能&#xff1a;实现“附近的人”距离计算 &#x1f30d;&#x1f4cd;为什么需要 Redis GEO&#xff1f;传统方案的痛点 &#x1f92f;❌ 问题显而易见&#xff1a;Redis GEO&#xff1a;专为 LBS 而生的解决方案 ✨核心优势&#xff1a;…

作者头像 李华
网站建设 2026/3/5 15:19:49

当海上风电遇上柔直并网:5MW风机群的300KV硬核操作手册

海上风电经柔直并网&#xff0c;单台风机容量5MW&#xff0c;总共60台风机&#xff0c;300MW。 柔直电压300KV&#xff0c;直流1KA。海风呼呼吹&#xff0c;风机转得欢。某风电场一口气怼了60台5MW风机&#xff0c;总容量300MW。这规模&#xff0c;相当于同时让30万台家用空调全…

作者头像 李华
网站建设 2026/3/7 1:58:11

书籍-伯希和《敦煌石窟图录》

伯希和《敦煌石窟图录》详细介绍 书籍基本信息 书名&#xff1a;敦煌石窟图录&#xff08;法文原名&#xff1a;Les Grottes de Touen-houang&#xff09; 作者&#xff1a;保罗伯希和&#xff08;Paul Pelliot&#xff0c;1878-1945年&#xff09; 成书时间&#xff1a;1920-1…

作者头像 李华
网站建设 2026/3/5 21:43:41

VS2015 + Qt 实现图形化Hello World(详细步骤)

本次实现基于VS2015Qt5.9.x&#xff08;兼容Qt5全系列&#xff09;&#xff0c;全程图形化UI操作&#xff0c;包含环境验证、项目创建、界面设计、代码编写、编译运行全流程&#xff0c;步骤精准可直接复刻。前提&#xff1a;确认VS2015的Qt插件已安装1. 打开VS2015&#xff0c…

作者头像 李华
网站建设 2026/3/6 16:29:57

毕业论文 AIGC 爆红?这几款论文降aigc神器,帮你实现一键降低ai率

交上去的论文&#xff0c;被系统标红“疑似AI生成” 论文初稿导师一看就说“你这用AI写的吧&#xff0c;一股机器味儿” 明明是自己想了半天的观点&#xff0c;却因为表达太像AI而被质疑 自己改写&#xff0c;但降AI率过程太折磨&#xff1a;要调整语序&#xff0c;要替换词…

作者头像 李华
网站建设 2026/3/6 11:38:54

2026年软件测试高需求技能路线图

一、行业变革&#xff1a;AI与云原生驱动的技能重构 2026年软件测试领域已进入智能化与云化深度融合阶段。据行业数据显示&#xff0c;AI测试自动化需求激增&#xff0c;掌握AI工具&#xff08;如Testim、Applitools&#xff09;的工程师平均年薪达$130,000&#xff0c;较传统…

作者头像 李华