vue实现表格输入
实现表格输入的基本思路
在Vue中实现表格输入功能,通常需要结合v-model指令进行数据双向绑定,同时利用v-for动态渲染表格行和列。核心是通过数组存储表格数据,每个单元格绑定到数组中的特定属性。
基础表格实现
<template>
<table>
<thead>
<tr>
<th v-for="(header, index) in headers" :key="index">{{ header }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, rowIndex) in tableData" :key="rowIndex">
<td v-for="(cell, cellIndex) in row" :key="cellIndex">
<input v-model="tableData[rowIndex][cellIndex]" />
</td>
</tr>
</tbody>
</table>
</template>
<script>
export default {
data() {
return {
headers: ['姓名', '年龄', '职业'],
tableData: [
['张三', '25', '工程师'],
['李四', '30', '设计师']
]
}
}
}
</script>
动态添加行功能
methods: {
addRow() {
this.tableData.push(Array(this.headers.length).fill(''))
}
}
在模板中添加按钮触发该方法:

<button @click="addRow">添加行</button>
对象结构的数据处理
更推荐使用对象数组存储数据,便于维护和扩展:
data() {
return {
headers: [
{ text: '姓名', value: 'name' },
{ text: '年龄', value: 'age' },
{ text: '职业', value: 'job' }
],
tableData: [
{ name: '张三', age: '25', job: '工程师' },
{ name: '李四', age: '30', job: '设计师' }
]
}
}
对应模板调整为:

<tr v-for="(row, rowIndex) in tableData" :key="rowIndex">
<td v-for="header in headers" :key="header.value">
<input v-model="row[header.value]" />
</td>
</tr>
表单验证处理
可以结合Vuelidate等验证库实现:
import { required, numeric } from 'vuelidate/lib/validators'
export default {
validations: {
tableData: {
$each: {
name: { required },
age: { required, numeric },
job: { required }
}
}
}
}
性能优化建议
对于大型表格,应考虑虚拟滚动技术或分页显示。可以使用第三方组件如vue-virtual-scroller:
<virtual-scroller :items="tableData" item-height="50">
<template v-slot="{ item }">
<tr>
<td v-for="header in headers" :key="header.value">
<input v-model="item[header.value]" />
</td>
</tr>
</template>
</virtual-scroller>
完整组件示例
<template>
<div>
<button @click="addRow">添加行</button>
<table>
<thead>
<tr>
<th v-for="header in headers" :key="header.value">{{ header.text }}</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index) in tableData" :key="index">
<td v-for="header in headers" :key="header.value">
<input
v-model="row[header.value]"
:class="{ error: $v.tableData.$each[index][header.value].$error }"
@blur="$v.tableData.$each[index][header.value].$touch()"
/>
</td>
<td>
<button @click="removeRow(index)">删除</button>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import { required, numeric } from 'vuelidate/lib/validators'
export default {
data() {
return {
headers: [
{ text: '姓名', value: 'name' },
{ text: '年龄', value: 'age' },
{ text: '职业', value: 'job' }
],
tableData: []
}
},
validations: {
tableData: {
$each: {
name: { required },
age: { required, numeric },
job: { required }
}
}
},
methods: {
addRow() {
this.tableData.push({
name: '',
age: '',
job: ''
})
},
removeRow(index) {
this.tableData.splice(index, 1)
}
}
}
</script>
<style>
.error {
border-color: red;
}
</style>






