目录
- 什么是动态表格
- 使用场景
- 基础实现方式
- 动态表格常用功能
- 使用第三方库实现动态表格
-
- [Element Plus](#Element Plus)
- [Naive UI](#Naive UI)
- 性能优化与注意事项
什么是动态表格
动态表格(Dynamic Table)是指:
- 表格结构和内容在运行时可以动态生成或修改。
- 表头和数据行不固定,可根据后端接口或前端逻辑生成。
- 支持排序、筛选、分页、可编辑、操作按钮等复杂交互。
区别于静态表格:静态表格表头固定,无法灵活应对动态数据。
使用场景
- 管理后台数据列表(用户管理、订单管理)
- 数据报表系统
- 可编辑的数据录入表格
- 数据对比与分析平台
基础实现方式
HTML + Vue 3
代码展示:
最基础的动态表格实现方式是利用 Vue 3 的 v-for 渲染表头和内容:
javascript
<template>
<table border="1">
<thead>
<tr>
<th v-for="column in columns" :key="column.key">
{{ column.label }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="row in tableData" :key="row.id">
<td v-for="column in columns" :key="column.key">
{{ row[column.key] }}
</td>
</tr>
</tbody>
</table>
</template>
<script setup>
import { ref } from 'vue'
const columns = ref([
{ key: 'id', label: 'ID' },
{ key: 'name', label: '姓名' },
{ key: 'age', label: '年龄' }
])
const tableData = ref([
{ id: 1, name: '张三', age: 18 },
{ id: 2, name: '李四', age: 22 },
{ id: 3, name: '王五', age: 20 }
])
</script>
特点:
- 表头和内容完全动态生成
- 可配合后端 API 动态加载数据(响应式数据绑定)
动态表格常用功能
排序
可以使用数组的 sort 或第三方库提供的排序功能:
javascript
<th @click="sort('age')">年龄</th>
<script setup>
const sort = (key) => {
tableData.value.sort((a, b) => a[key] - b[key])
}
</script>
筛选
使用 computed 来过滤数据:
javascript
<input v-model="searchName" placeholder="搜索姓名" />
<tr v-for="row in filteredData" :key="row.id">
...
</tr>
<script setup>
import { ref, computed } from 'vue'
const searchName = ref('')
const filteredData = computed(() =>
tableData.value.filter(row => row.name.includes(searchName.value))
)
</script>
分页
简单的分页逻辑:
javascript
const currentPage = ref(1)
const pageSize = ref(5)
const pagedData = computed(() => {
const start = (currentPage.value - 1) * pageSize.value
return tableData.value.slice(start, start + pageSize.value)
})
可编辑单元格
结合 v-model 实现单元格编辑:
javascript
<td v-for="column in columns" :key="column.key">
<input v-model="row[column.key]" />
</td>
使用第三方库实现动态表格
Element Plus
javascript
<template>
<el-input v-model="searchName" placeholder="搜索姓名" style="margin-bottom: 10px;" />
<el-table :data="filteredData" style="width: 100%">
<el-table-column prop="id" label="ID" sortable></el-table-column>
<el-table-column prop="name" label="姓名" sortable>
<template #default="{ row }">
<el-input v-model="row.name"></el-input>
</template>
</el-table-column>
<el-table-column prop="age" label="年龄" sortable></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column>
</el-table>
<el-pagination
v-model:current-page="currentPage"
:page-size="pageSize"
:total="tableData.length"
style="margin-top: 10px;"
></el-pagination>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import axios from 'axios'
const tableData = ref([])
const searchName = ref('')
const currentPage = ref(1)
const pageSize = ref(5)
onMounted(async () => {
const res = await axios.get('/api/users')
tableData.value = res.data
})
const filteredData = computed(() => {
const filtered = tableData.value.filter(row => row.name.includes(searchName.value))
const start = (currentPage.value - 1) * pageSize.value
return filtered.slice(start, start + pageSize.value)
})
</script>
Naive UI
javascript
<template>
<n-data-table
:columns="columns"
:data="tableData"
:bordered="true"
/>
</template>
<script setup>
import { ref, h } from 'vue'
import { NButton } from 'naive-ui'
const columns = [
{ title: 'ID', key: 'id' },
{ title: '姓名', key: 'name' },
{ title: '年龄', key: 'age' },
{
title: '操作',
key: 'actions',
render(row) {
return h(NButton, { type: 'primary', size: 'small', onClick: () => alert('编辑: ' + row.name) }, { default: () => '编辑' })
}
}
]
const tableData = ref([
{ id: 1, name: '张三', age: 18 },
{ id: 2, name: '李四', age: 22 }
])
</script>
特点:
- columns 配置化
- 支持 render 自定义渲染单元格
- 非常适合中后台业务系统
性能优化与注意事项
- 大数据量表格建议使用虚拟滚动(Element Plus virtual-scroll 或 Naive UI virtual-scroll)
- 避免在 v-for 中写复杂逻辑,尤其是计算密集型操作
- 分页、筛选尽量在服务端处理,避免一次性加载全部数据
- 自定义操作列用 render或插槽,保持表格组件可复用