本文完整版:《在 Vue3 + Element Plus 中生成动态表格,动态修改表格,多级表头,合并单元格》
在 Vue 中,表格组件是使用频率及复杂度排名第一的组件,前端经常需要根据后台返回的数据动态渲染表格,比如动态表格如何生成,因为表格的列并不是固定的,在未知表格具体有哪些列的场景下,前端如何动态渲染表格数据。又或者需要把表格单元格进行合并处理,比如第一列是日期,需要把相同的日期进行合并,这样表格看起来会更加清晰。 本文手把手教你如何在 Vue3 + Element Plus 中创建表格、生成动态表格、创建动态多级表头、表格行合并、列合并等问题。
如果你正在搭建后台管理工具,又不想处理前端问题,推荐使用卡拉云 ,卡拉云是新一代低代码开发工具,可一键接入常见数据库及 API ,无需懂前端,仅需拖拽即可快速搭建属于你自己的后台管理工具,一周工作量缩减至一天,详见本文文末。
通过本文你可以学到
先来展示个「动态修改表格」的最终效果图吧
先使用 vue-cli 初始化应用,这里我们选择 vue3 的版本:
vue create kalacloud-vue3-element-plus-table
// OR
npx vue create kalacloud-vue3-element-plus-table
然后安装 UI 框架 Element Plus:
npm install element-plus --save
// OR
yarn add element-plus
安装完成后,在项目里导入 ElementPlus,修改 main.js 如下:
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
导入后,就可以启动项目了,执行以下命令:
看到以下界面说明项目成功启动了!后面就可以进入本教程的正式内容了。
有一个场景是表格列并不是固定的,不能在前端写死,而是需要通过后端返回的数据进行动态渲染,比如后端返回了如下的表头数据:
tableHeader: {
name: "姓名",
birth: "生日",
address: "地址",
age: "年龄",
phone: "电话",
}
这个对象中的 key
对应表格数据中的 prop
,value
对应实际显示的 label
,这样通过一个简单的对象,就可以连接表头和 表格body
之间的关系。然后还需要后端返回具体的表格数据:
tableData: [{
name: '张三',
date: '2016-05-02',
address: '上海市普陀区金沙江路 1518 弄',
age: 18,
phone:"12345678910",
}, {
date: '2016-05-04',
name: '李四',
address: '上海市普陀区金沙江路 1517 弄',
age: 19,
phone:"12345678911",
}, {
date: '2016-05-01',
name: '王五',
address: '上海市普陀区金沙江路 1519 弄',
age: 20,
phone:"12345678912",
}, {
date: '2016-05-03',
name: '赵六',
address: '上海市普陀区金沙江路 1516 弄',
age: 21,
phone:"12345678913",
}]
实现表格列动态渲染的功能,需要用到一个很关键的 vue
指令,那就是 v-for
,v-for
不仅可以遍历数据,也可以遍历对象:
{{ key }}: {{ value }}
这里我们就需要用到这个特性,来对 tableHeader
进行遍历,获取 key
和 value
。基于以上讲解,现在我们具体实践一下如何实现表格列的动态渲染。在 components
目录中新建 DynamicTable.vue
:
Vue3 + Element plus 动态表格
组件编写完成后,修改 App.vue,导入该组件即可:
保存后页面会自动热更新,实现效果如下:
这个只是比较基本的使用,如果某些列有一些定制需求,比如需要支持根据日期排序,这个时候可以对 tableHeader
进行改造,使 value
是一个对象,这样就可以携带更多的表头配置信息:
tableHeader: {
name: {
label: "姓名",
sort: true,
},
birth: {
label: "生日",
sort: false,
},
address: {
label: "地址",
sort: false,
},
age: {
label: "年龄",
sort: true,
},
phone: {
label: "电话",
sort: false,
}
},
然后再改造 el-table 如下:
以上就实现了基于动态列的表头配置,这里的关键在于 tableHeader
的数据结构如何定义,可以把列信息都放在 tableHeader
中,然后再通过 v-for 循环列就可以渲染出对应的表格列。当然 tableHeader
也可以是一个数组,使用方法都是类似的,大家可以自己去尝试一下。
扩展阅读:《多款好用的 vue 表单设计器推荐测评》
基于以上的思路,我们还可以做的更多,比如动态添加指定行,指定列,或者删除指定行或者列等操作,都是使用相同的思路来实现。我们来具体实践一下,这里我们需要用到 @element-plus/icons-vue
,先安装一下:
# NPM
npm install @element-plus/icons-vue
# Yarn
yarn add @element-plus/icons-vue
然后在 main.js 中导入:
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
在 components
目录下新建 DynamicModifyTable.vue
:
Vue3 + Element plus 动态修改表格
「卡拉云 - 极速搭建企业内部工具,十倍提升开发效率」
{{ scope.row[item.prop] }}
编辑
确定
删除
对于 `tableHeader` 的定义,我们通过 `children` 字段来指定当前列的二级表头,但是会发现效果并不是我们预期的那样:
![kalacloud-卡拉云-错误演示动态多级表头](./images/04-kalacloud-vue3-element-plug-error.png "04-kalacloud-vue3-element-plug-error.png")
这是为什么呢?原来是因为 `el-table-column` 会检测内部是否还有 `el-table-column`,如果有的话,默认会显示内层的 `el-table-column`,但是在一级表头的情况下,内层 `el-table-column` 并没有值。所以我们需要简单修改一下代码,那就是通过 `v-if="item.children"` 来判断当前列是否有二级表头:
```html
如果不这么做,那就只能渲染有二级表头的列,无法正常显示一级表头的数据, 最后的效果如下:
扩展阅读:《12款最棒的 Vue ui 组件库框架 推荐测评》
我们先来看下如何实现行合并,行合并或者是列合并,都需要用到 el-table
中 span-method
这个方法,在官方的例子中,是通过固定返回 rowspan
,colspan
来实现行合并的:
const objectSpanMethod = ({
row,
column,
rowIndex, // 需要合并的开始行
columnIndex, // 需要合并的列
}) => {
if (columnIndex === 0) {
if (rowIndex % 2 === 0) {
return {
rowspan: 2, //合并的行数
colspan: 1, //合并的列数
}
} else {
return {
rowspan: 0,
colspan: 0,
}
}
}
}
但是在动态数据的场景下,这种方法就不适用了,因为前端的表格数据往往是后端通过接口返回的。比如我们有以下数据结构:
tableData: [{
name: '张三',
province: "上海市",
city: "普陀区",
address: "金沙江路 1518 弄",
birth: '2016-05-02',
phone: "12345678910",
}, {
name: '李四',
birth: '2016-05-02',
province: "上海市",
city: "普陀区",
address: '金沙江路 1517 弄',
age: 19,
phone: "12345678911",
}, {
name: '王五',
birth: '2016-05-03',
province: "上海市",
city: "普陀区",
address: '金沙江路 1519 弄',
phone: "12345678912",
}, {
name: '赵六',
birth: '2016-05-04',
province: "上海市",
city: "普陀区",
address: '金沙江路 1516 弄',
phone: "12345678913",
}, {
name: '孙七',
birth: '2016-05-04',
province: "上海市",
city: "普陀区",
address: '金沙江路 1516 弄',
phone: "12345678913",
}, {
name: '周八',
birth: '2016-05-04',
province: "上海市",
city: "普陀区",
address: '金沙江路 1516 弄',
phone: "12345678913",
}, {
name: '吴九',
birth: '2016-05-06',
province: "上海市",
city: "普陀区",
address: '金沙江路 1516 弄',
phone: "12345678913",
}]
我们的需求是把相同 birth
进行合并。在 components
目录下新建 RowMergeTable.vue
文件:
Vue3 + Element plus 动态行合并表格
上面的例子就实现了行合并的功能:
因为表格的数据是动态的,所以我们需要事先通过计算,来得知哪些行是需要合并的,这里就是通过 getSpanArr
方法来实现的,全局维护了一个 spanArr
变量,用于记录每一行需要合并的数字,pos
是 spanArr
的索引,这样就可以根据索引来动态设置需要合并的行树。当 i === 0
,说明是第一行数据,向 spanArr
数组中 push
1,当 i !== 0
,此时就需要比较当前行与前一行数据的 birth
是否相等,如果相等,则利用索引,修改当前行需要合并的行数。
objectSpanMethod
方法,在 el-table
渲染每一行数据的时候都会执行,这样就可以通过 rowIndex
来获取每一行需要合并的行数信息,来实现行合并的功能。
那么如何实现多行合并?其实也是一样的思路,通过 spanMap
可以存储多个列的行合并信息。在 components
下新建 MultiRowMergeTable.vue
:
Vue3 + Element plus 动态多行合并表格
实现效果如下:
动态多行合并的需求往往更常见,需要把每一列中,相同的数据进行合并,都可以参照这个思路来实现。
扩展阅读:《Vue + Node.js 全栈开发实战教程 - 手把手教你搭建「文件上传」管理后台》
接下来,我们来看下如何实现列的合并,其实思路是和行合并类似的,也需要用到 span-method
这个方法,唯一不同的在于,列合并需要处理被合并列的原始数据,否则被合并列的原始数据会填充到合并之后的表格里,这样说可能有点抽象,我们写来写一个例子,在 components 下新建 ColumnMergeTable.vue:
Vue3 + Element plus 动态表格列合并
可以看出来,列合并其实比行合并简单一些,返回一个数组更容易理解一些,数组的第一项表示合并的起始列,第二项表示合并的终止列,其区间的所有列都会合并成一列,被合并的列还需要通过 [0, 0] 来隐藏对应的单元格,这个是和行合并不同的地方。
扩展阅读:《Vue echarts 使用教程》
本教程所写源代码可在我们的 github 上找到。
本文详细讲解如何 Vue3 + Element Plus 中如何创建动态表格的问题。其实如果你根本不想处理复杂的前端问题,完全可以使用卡拉云来处理前端表格,卡拉云内置表格组件,直接鼠标拖拽即可生成,不仅可以处理动态表格,内容实时编辑以及表格中展示图片等功能,还有强大的过滤筛选、数据导出功能。
卡拉云可帮你快速搭建企业内部工具,下图为使用卡拉云搭建的内部广告投放监测系统,无需懂前端,仅需拖拽组件,10 分钟搞定。你也可以快速搭建一套属于你的后台管理工具。
卡拉云是新一代低代码开发平台,与前端框架 Vue、React等相比,卡拉云的优势在于不用首先搭建开发环境,直接注册即可开始使用。开发者完全不用处理任何前端问题,只需简单拖拽,即可快速生成所需组件,可一键接入常见数据库及 API,根据引导简单几步打通前后端,数周的开发时间,缩短至 1 小时。立即免费试用卡拉云。
扩展阅读: