动态表格在 Vue 3 中的实现指南【前端】

目录

什么是动态表格

动态表格(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或插槽,保持表格组件可复用
相关推荐
benbenAItalk7 小时前
数字人口播视频的批量生产实践:素材规范、任务编排与质量验收
java·前端·音视频
2601_962885727 小时前
如何用 Python 扫描 A 股跳空缺口并统计缺口回补概率?
java·前端·python
西瓜太郎12348 小时前
Claude Code、Codex CLI、Gemini CLI 能否共用一枚 Key?先看协议选择矩阵
前端·api 网关·claude code·gemini cli·codex cli
多加点辣也没关系8 小时前
JavaScript|第31章:表单与控件
开发语言·javascript·ecmascript
陈随易10 小时前
在Finch用了62亿词元,我认为这是新一代Agent工具之神
前端·人工智能·后端
水域安全老周10 小时前
水趣钓鱼救生衣专利拆解:两级锁紧如何解决落水人衣分离
java·前端·网络
计算机魔术师10 小时前
Anthropic CEO突然喊踩刹车,OpenAI罕见力挺:AI这辆车不能只踩油门了
前端
wing9811 小时前
从codex转战workbuddy使用一周的感受
前端·人工智能·后端
Highcharts.js11 小时前
常见报错排雷指南2:导出失败的官方解法
javascript·react.js·ecmascript·highcharts·可视化图表·导出模块失败·导出服务
EatFan11 小时前
Java接入支付宝 JSAPI 支付保姆教程(二):流程讲解与前后端代码讲解
前端·spring boot·后端·微信小程序·小程序·uni-app