前言在前端开发中,我们经常会遇到这样的需求场景需要展示大量数据的树形结构表格,并且要在表格单元格内插入输入框、选择器、开关等可交互元素。传统的表格组件往往在面对这种复杂场景时力不从心性能问题、功能不足、配置复杂等问题接踵而至。这时候,vxe-table就成为了一个理想的解决方案。本文将详细介绍 vxe-table 的核心功能和使用方法,帮助大家快速上手这个强大的表格组件。一、vxe-table 简介1.1 什么是 vxe-tablevxe-table 是一个基于 Vue 的 PC 端表格组件,支持增删改查、虚拟滚动、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、自定义模板等强大功能。官网地址https://vxetable.cnGitHubhttps://github.com/x-extends/vxe-table1.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-utils2.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 :datatableData vxe-column fieldid titleID width80/vxe-column vxe-column fieldname title姓名 width150/vxe-column vxe-column fieldage title年龄 width100/vxe-column vxe-column fieldaddress 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: 广州市天河区 } ]) /script3.2 树形表格vxe-table 对树形结构有原生支持template div vxe-table :datatreeData :tree-config{ children: children, expandAll: true } border vxe-column fieldname title部门名称 tree-node/vxe-column vxe-column fieldleader title负责人 width150/vxe-column vxe-column fieldcount title人数 width100/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 :datatableData :edit-config{ trigger: click, mode: cell } vxe-column fieldname title姓名 :edit-render{ name: input }/vxe-column vxe-column fieldage 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 :datatableData :edit-config{ trigger: click, mode: cell } vxe-column fieldname title姓名/vxe-column vxe-column fieldstatus title状态 :edit-render{ name: select, options: statusOptions } /vxe-column vxe-column fieldrole 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 :datatableData :edit-config{ trigger: click, mode: cell } vxe-column fieldname title姓名/vxe-column vxe-column fieldbirthday 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 :datatableData :edit-config{ trigger: click, mode: cell } vxe-column fieldname title姓名/vxe-column vxe-column fieldenabled 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 } ]) /script4.2 自定义渲染器(插槽)对于更复杂的场景,可以使用插槽自定义渲染template vxe-table :datatableData :edit-config{ trigger: click, mode: cell } vxe-column fieldname title姓名/vxe-column vxe-column fieldtags title标签 template #edit{ row } el-select v-modelrow.tags multiple placeholder请选择标签 el-option labelVue valuevue/el-option el-option labelReact valuereact/el-option el-option labelAngular valueangular/el-option /el-select /template template #default{ row } span v-fortag in row.tags :keytag classtag{{ 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 classdemo-container vxe-toolbar template #buttons vxe-button clickinsertEvent新增/vxe-button vxe-button clicksaveEvent保存/vxe-button vxe-button clickremoveSelectEvent删除选中/vxe-button /template /vxe-toolbar vxe-table reftableRef border resizable :datatableData :tree-configtreeConfig :edit-config{ trigger: click, mode: cell } :checkbox-config{ checkStrictly: true } vxe-column typecheckbox width60/vxe-column vxe-column typeseq width60 title序号/vxe-column vxe-column fieldname title部门名称 tree-node :edit-render{ name: input } /vxe-column vxe-column fieldleader title负责人 :edit-render{ name: input } /vxe-column vxe-column fieldstatus title状态 :edit-render{ name: select, options: statusOptions } template #default{ row } span :classstatus- row.status {{ getStatusLabel(row.status) }} /span /template /vxe-column vxe-column fieldcount title人数 :edit-render{ name: input, props: { type: number, min: 0 } } /vxe-column vxe-column fieldenabled title启用 width100 :edit-render{ name: $switch } template #default{ row } span{{ row.enabled ? 是 : 否 }}/span /template /vxe-column vxe-column title操作 width200 template #default{ row } vxe-button typetext clickinsertChildEvent(row)添加子项/vxe-button vxe-button typetext statusdanger clickremoveEvent(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 height600 :datatableData :scroll-y{ enabled: true, gt: 100 } vxe-column fieldid titleID width80/vxe-column vxe-column fieldname title姓名/vxe-column vxe-column fieldage 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 })) ) /script6.2 数据校验vxe-table 支持强大的数据校验功能template vxe-table :datatableData :edit-config{ trigger: click, mode: cell } :edit-ruleseditRules vxe-column fieldname title姓名 :edit-render{ name: input } /vxe-column vxe-column fieldemail title邮箱 :edit-render{ name: input } /vxe-column vxe-column fieldage 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: zhangsanexample.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 之间 } ] } /script6.3 导出 Exceltemplate div vxe-button clickexportExcel导出Excel/vxe-button vxe-table reftableRef :datatableData vxe-column fieldname title姓名/vxe-column vxe-column fieldage 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七、性能优化建议使用虚拟滚动数据量大于 100 条时开启虚拟滚动按需加载只引入需要的组件和功能模块懒加载树节点树形数据较大时使用懒加载避免过度渲染合理使用show-overflow属性分页加载超大数据集使用分页而非一次性加载template vxe-table border height600 show-overflow :datatableData :scroll-y{ enabled: true } :tree-config{ lazy: true, loadMethod: loadChildrenMethod } vxe-column fieldname 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-configvxe-table :edit-config{ trigger: click, mode: cell }8.2 树形数据不显示问题树形结构没有展示出来解决确保配置了tree-config和tree-nodevxe-table :tree-config{ children: children } vxe-column fieldname title名称 tree-node/vxe-column /vxe-table8.3 下拉选择器选项不显示问题select 渲染器的选项列表为空解决确保 options 格式正确,必须包含 label 和 valueconst options [ { label: 选项1, value: 1 }, // 正确 { label: 选项2, value: 2 } ]九、总结vxe-table 是一个功能强大、性能优秀的 Vue 表格组件,特别适合处理复杂的业务场景支持树形结构和大数据量虚拟滚动内置丰富的表单渲染器(输入框、选择器、开关等)灵活的单元格编辑和数据校验完善的 API 和良好的扩展性对于需要在表格中插入输入框、选择器等交互元素的场景,vxe-table 提供了开箱即用的解决方案,大大提升了开发效率。建议大家在实际项目中根据具体需求,合理使用 vxe-table 的各项功能,同时注意性能优化,以获得最佳的用户体验。参考资料vxe-table 官方文档vxe-table GitHubvxe-table 示例提示本文基于 vxe-table 4.x 版本编写,如有版本差异请参考官方文档。