Vue實現(xiàn)極致舒適的可編輯表格
使用ElementPlus的Table啥都好,就是沒有可編輯表格?。?!
既然UI庫不支持,那我們實現(xiàn)一個可編輯表格是很難的事么?難么?不難么?...
個人覺得如果是業(yè)務固定的可編輯表格,使用ElementPlus實現(xiàn)都不難。但是如果需要的是一個通用的可編輯表格,這好像還真說不好。
對于通用的可編輯表格,網(wǎng)上的實現(xiàn)方案也是五花八門,但是看下來多少都有些問題。個人認為一個通用的可編輯表格需要給使用方提供以下能力:
- 支持新增、刪除、編輯、保存
- 定義可編輯列
- 定義表單組件,既可以是原生標簽,也可以是自定義組件
- 定義表單校驗規(guī)則
- 定義數(shù)據(jù)展示部分
- 定義操作區(qū)域
- 幾乎無學習成本
實現(xiàn)了以上需求的可編表格,就可以滿足基本的生產(chǎn)需求了。
在<el-table>組件的基礎上實現(xiàn)可編輯表格,保留<el-table>的使用方式不變,還能提供可編輯功能。同時可編輯功能的配置與<el-table>的使用風格一致,降低學習成本。
準備數(shù)據(jù)
const tableData = [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
]基礎表格
基礎表格的用法與<el-table>幾乎沒有區(qū)別,唯一的不同就是<el-table>中的data,在<EditTable>中被data-source替換。

<section>
<h1>無編輯效果</h1>
<EditTable class="edit-table" :data-source="tableData">
<EditTableColumn prop="date" label="時間"> </EditTableColumn>
<EditTableColumn prop="name" label="姓名"> </EditTableColumn>
<EditTableColumn prop="address" label="地址"> </EditTableColumn>
</EditTable>
</section>可修改表格
<EditTableColumn>存在一個#default默認插槽和一個#edit具名插槽,默認插槽和具名插槽都提供了row、actions、$index等值。
可修改表格是在基礎表格上給<EditTableColumn>添加名為edit的具名插槽<template #edit>。
- 通過
row可以獲取到當前行的數(shù)據(jù)。插槽中的表單組件可通過v-model="row.*"對編輯值進行雙向綁定。 - 通過
actions可以獲取編輯表格的能力,通過action.startEditable($index)開啟編輯,action.cancelEditable($index)取消編輯,action.saveEditable保存編輯。

<section>
<h1>可編輯效果</h1>
<EditTable class="edit-table" :data-source="tableData">
<EditTableColumn prop="date" label="時間">
<template #edit="{ row }">
<input v-model="row.date" />
</template>
</EditTableColumn>
<EditTableColumn prop="name" label="姓名">
<template #edit="{ row }">
<input v-model="row.name" />
</template>
</EditTableColumn>
<EditTableColumn prop="address" label="地址">
<template #edit="{ row }">
<input v-model="row.address" />
</template>
</EditTableColumn>
<EditTableColumn label="操作">
<template #default="{ actions, $index }">
<button @click="actions.startEditable($index)">操作</button>
</template>
<template #edit="{ actions, $index }">
<button @click="actions.saveEditable($index)">保存</button>
<button @click="actions.cancelEditable($index)">取消</button>
</template>
</EditTableColumn>
</EditTable>
</section>刪除效果
在上述表格的操作區(qū)域增加刪除按鈕,刪除按鈕點擊時調用actions.delete($index)用來刪除當前行。

<section>
<h1>刪除效果</h1>
<EditTable class="edit-table" :data-source="tableData">
<EditTableColumn prop="date" label="時間">
<template #edit="{ row }">
<input v-model="row.date" />
</template>
</EditTableColumn>
<EditTableColumn prop="name" label="姓名">
<template #edit="{ row }">
<input v-model="row.name" />
</template>
</EditTableColumn>
<EditTableColumn prop="address" label="地址">
<template #edit="{ row }">
<input v-model="row.address" />
</template>
</EditTableColumn>
<EditTableColumn label="操作">
<template #default="{ actions, $index }">
<button @click="actions.startEditable($index)">操作</button>
<button @click="actions.deleteRow($index)">刪除</button>
</template>
<template #edit="{ actions, $index }">
<button @click="actions.saveEditable($index)">保存</button>
<button @click="actions.cancelEditable($index)">取消</button>
<button @click="actions.deleteRow($index)">刪除</button>
</template>
</EditTableColumn>
</EditTable>
</section>新增效果
組件<EditTable>并不需要提供新增按鈕,如果直接將新增按鈕封裝在組件內,那么這個組件就太呆了。因此<EditTable>只提供了actions.addRow方法,調用方可以根據(jù)自己的需求完成新增功能。

<script lang="ts" setup>
import { ref } from 'vue';
import EditTable from '@/components/EditTable.vue';
import EditTableColumn from '@/components/EditTableColumn.vue';
const tableData = [...];
const addEditTableRef = ref<InstanceType<typeof EditTable>>();
</script>
<template>
<div class="wrapper">
<section>
<h1>新增效果</h1>
<EditTable ref="addEditTableRef" class="edit-table" :data-source="tableData">
<EditTableColumn prop="date" label="時間">
<template #edit="{ row }">
<input v-model="row.date" />
</template>
</EditTableColumn>
<EditTableColumn prop="name" label="姓名">
<template #edit="{ row }">
<input v-model="row.name" />
</template>
</EditTableColumn>
<EditTableColumn prop="address" label="地址">
<template #edit="{ row }">
<input v-model="row.address" />
</template>
</EditTableColumn>
<EditTableColumn label="操作">
<template #default="{ actions, $index }">
<button @click="actions.startEditable($index)">操作</button>
<button @click="actions.deleteRow($index)">刪除</button>
</template>
<template #edit="{ actions, $index }">
<button @click="actions.saveEditable($index)">保存</button>
<button @click="actions.cancelEditable($index)">取消</button>
<button @click="actions.deleteRow($index)">刪除</button>
</template>
</EditTableColumn>
</EditTable>
<button @click="addEditTableRef?.editActions.addRow()">新增</button>
</section>
</div>
</template>表單校驗
組件<EditTableColumn>允許驗證用戶的輸入是否符合規(guī)范,來找到和糾正錯誤。只需要為<EditTableColumn :rules="rules">的rules屬性傳入約定的驗證規(guī)則,高級用法可參考async-validator。
總之校驗規(guī)則和表單的校驗規(guī)則一致。

<section>
<h1>表單校驗效果</h1>
<EditTable ref="formEditTableRef" class="edit-table" :data-source="tableData">
<EditTableColumn
prop="date"
label="時間"
:rules="[{ required: true, message: '時間是必填項', trigger: 'blur' }]"
>
<template #edit="{ row }">
<input v-model="row.date" />
</template>
</EditTableColumn>
<EditTableColumn
prop="name"
label="姓名"
:rules="[{ required: true, message: '姓名是必填項', trigger: 'blur' }]"
>
<template #edit="{ row }">
<input v-model="row.name" />
</template>
</EditTableColumn>
<EditTableColumn
prop="address"
label="地址"
:rules="[{ required: true, message: '地址是必填項', trigger: 'blur' }]"
>
<template #edit="{ row }">
<input v-model="row.address" />
</template>
</EditTableColumn>
<EditTableColumn label="操作">
<template #default="{ actions, $index }">
<button @click="actions.startEditable($index)">操作</button>
<button @click="actions.deleteRow($index)">刪除</button>
</template>
<template #edit="{ actions, $index }">
<button @click="actions.saveEditable($index)">保存</button>
<button @click="actions.cancelEditable($index)">取消</button>
<button @click="actions.deleteRow($index)">刪除</button>
</template>
</EditTableColumn>
</EditTable>
<button @click="formEditTableRef?.editActions.addRow()">新增</button>
</section>獲取編輯后的表單數(shù)據(jù)
組件<EditTable>對外暴露了resultData響應式對象,可以用來獲取表格的最新數(shù)據(jù)。

<section>
<h1>獲取編輯結果</h1>
<EditTable ref="formEditTableRef" class="edit-table" :data-source="tableData">
<EditTableColumn
prop="date"
label="時間"
:rules="[{ required: true, message: '時間是必填項', trigger: 'blur' }]"
>
<template #edit="{ row }">
<input v-model="row.date" />
</template>
</EditTableColumn>
<EditTableColumn
prop="name"
label="姓名"
:rules="[{ required: true, message: '姓名是必填項', trigger: 'blur' }]"
>
<template #edit="{ row }">
<input v-model="row.name" />
</template>
</EditTableColumn>
<EditTableColumn
prop="address"
label="地址"
:rules="[{ required: true, message: '地址是必填項', trigger: 'blur' }]"
>
<template #edit="{ row }">
<input v-model="row.address" />
</template>
</EditTableColumn>
<EditTableColumn label="操作">
<template #default="{ actions, $index }">
<button @click="actions.startEditable($index)">操作</button>
<button @click="actions.deleteRow($index)">刪除</button>
</template>
<template #edit="{ actions, $index }">
<button @click="actions.saveEditable($index)">保存</button>
<button @click="actions.cancelEditable($index)">取消</button>
<button @click="actions.deleteRow($index)">刪除</button>
</template>
</EditTableColumn>
</EditTable>
<button @click="formEditTableRef?.editActions.addRow()">新增</button>
<p>獲取數(shù)據(jù):{{ formEditTableRef?.resultData }}</p>
</section>另一種數(shù)據(jù)配置
組件<EditTable>除了支持data-source的方式配置數(shù)據(jù)外,還支持request屬性傳入返回數(shù)據(jù)的函數(shù)。

<script lang="ts" setup name="Page-B">
import { ref } from 'vue';
import EditTable from '@/components/EditTable.vue';
import EditTableColumn from '@/components/EditTableColumn.vue';
const loadData = async () => [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles',
},
];
</script>
<template>
<div class="wrapper">
<section>
<h1>另一種數(shù)據(jù)配置</h1>
<EditTable class="edit-table" :request="loadData">
<EditTableColumn prop="date" label="時間"> </EditTableColumn>
<EditTableColumn prop="name" label="姓名"> </EditTableColumn>
<EditTableColumn prop="address" label="地址"> </EditTableColumn>
</EditTable>
</section>
</div>
</template>以上就是Vue實現(xiàn)極致舒適的可編輯表格的詳細內容,更多關于Vue可編輯表格的資料請關注腳本之家其它相關文章!
相關文章
Vue3中是如何實現(xiàn)數(shù)據(jù)響應式示例詳解
這篇文章主要介紹了Vue3中是如何實現(xiàn)數(shù)據(jù)響應式示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07
從Vue2升級Vue3過程中遇到作用域插槽語法變更問題的解決方法
在將項目從 Vue 2 升級到 Vue 3 的過程中,遇到了兩處典型的兼容性問題,主要涉及 作用域插槽語法變更 和 響應式數(shù)據(jù)類型處理差異,本文通過具體代碼示例,說明問題原因、Vue 版本機制差異,并給出推薦改法,需要的朋友可以參考下2026-02-02
一文帶你重新學習Vue中的按鍵監(jiān)聽和鼠標監(jiān)聽
這篇文章主要為大家詳細介紹了Vue中的按鍵監(jiān)聽和鼠標監(jiān)聽的常見實現(xiàn)方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2025-07-07

