需求背景:
????????在現代前端開發中,表格作為數據展示和交互的重要組件,在各類管理系統、數據平臺中有著廣泛的應用。隨著用戶對數據操作便捷性要求的不斷提高,具備靈活編輯功能的表格成為了開發中的常見需求。特別是在需求處理大量數據時,不僅要實現數據的分頁展示,還要支持對數據的實時編輯,并且要保證在復雜操作場景下的數據狀態管理。
????????本次demo是人員信息管理的場景。
????????在該場景下,需要一個能夠展示人員基本信息(包括ID、姓名、年齡、職業、愛好等)的表格,同時要求具備強大的編輯功能。具體來說,需要在表格中實現編輯按鈕,點擊后能對該行的職業和愛好進行修改,其中職業通過文本框編輯,愛好通過下拉框選擇。此外,考慮到數據量較大的情況,表格需要支持分頁展示,每頁展示5條數據為例。更為關鍵的是,要實現多行數據同時編輯的功能,并且在切換分頁時,能將數據恢復到初始化狀態,確保用戶操作的一致性和數據展示的準確性,提升系統的易用性和交互體驗。
代碼展示:
<script setup lang="ts">
import { ref, computed } from 'vue'
import { ElTable, ElTableColumn, ElPagination, ElButton, ElInput, ElSelect, ElOption } from 'element-plus'interface TableItem {id: numbername: stringage: numberprofession: stringhobby: stringisEditing: booleanoriginalData?: {profession: stringhobby: string}
}const hobbies = ['讀書', '運動', '音樂', '旅游', '游戲']const tableData = ref<TableItem[]>([{ id: 1, name: '張三', age: 25, profession: '工程師', hobby: '讀書', isEditing: false },{ id: 2, name: '李四', age: 28, profession: '設計師', hobby: '運動', isEditing: false },{ id: 3, name: '王五', age: 30, profession: '教師', hobby: '音樂', isEditing: false },{ id: 4, name: '趙六', age: 22, profession: '學生', hobby: '游戲', isEditing: false },{ id: 5, name: '錢七', age: 35, profession: '醫生', hobby: '旅游', isEditing: false },{ id: 6, name: '孫八', age: 27, profession: '銷售', hobby: '運動', isEditing: false },{ id: 7, name: '周九', age: 32, profession: '會計', hobby: '讀書', isEditing: false },{ id: 8, name: '吳十', age: 29, profession: '律師', hobby: '音樂', isEditing: false },{ id: 9, name: '鄭十一', age: 31, profession: '記者', hobby: '旅游', isEditing: false },{ id: 10, name: '王十二', age: 26, profession: '作家', hobby: '游戲', isEditing: false },
])const currentPage = ref(1)
const pageSize = ref(5)const paginatedData = computed(() => {const start = (currentPage.value - 1) * pageSize.valueconst end = start + pageSize.valuereturn tableData.value.slice(start, end)
})const handleEdit = (row: TableItem) => {row.isEditing = truerow.originalData = {profession: row.profession,hobby: row.hobby}
}const handleSave = (row: TableItem) => {row.isEditing = false;// 實際開發中,調用接口,是否使用delete row.originalData視情況而定delete row.originalData
}const handleCancel = (row: TableItem) => {
// 取消操作時,務必還原之前的數據if (row.originalData) {row.profession = row.originalData.professionrow.hobby = row.originalData.hobby}row.isEditing = false// 實際開發中,調用接口,是否使用delete row.originalData視情況而定delete row.originalData
}const handlePageChange = (page: number) => {currentPage.value = page;// Reset editing state for all rows,僅為靜態數據展示使用;實際開發調用接口,無需單獨處理tableData.value.forEach(row => {if (row.isEditing) {handleCancel(row)}})
}
</script><template><div class="table-container"><el-table :data="paginatedData" style="width: 100%"><el-table-column prop="id" label="ID" width="80" /><el-table-column prop="name" label="姓名" width="120" /><el-table-column prop="age" label="年齡" width="80" /><el-table-column label="職業" width="180"><template #default="{ row }"><el-inputv-if="row.isEditing"v-model="row.profession"size="small"/><span v-else>{{ row.profession }}</span></template></el-table-column><el-table-column label="愛好" width="180"><template #default="{ row }"><el-selectv-if="row.isEditing"v-model="row.hobby"size="small"style="width: 100%"><el-optionv-for="hobby in hobbies":key="hobby":label="hobby":value="hobby"/></el-select><span v-else>{{ row.hobby }}</span></template></el-table-column><el-table-column label="操作" width="180"><template #default="{ row }"><template v-if="row.isEditing"><el-button type="success" size="small" @click="handleSave(row)">保存</el-button><el-button type="info" size="small" @click="handleCancel(row)">取消</el-button></template><el-button v-else type="primary" size="small" @click="handleEdit(row)">編輯</el-button></template></el-table-column></el-table><div class="pagination"><el-paginationv-model:current-page="currentPage":page-size="pageSize":total="tableData.length"layout="prev, pager, next"@current-change="handlePageChange"/></div></div>
</template><style scoped>
.table-container {width: 100%;max-width: 1000px;margin: 0 auto;
}.pagination {margin-top: 20px;display: flex;justify-content: center;
}.el-button {margin-right: 8px;
}.el-button:last-child {margin-right: 0;
}
</style>
上面代碼僅為靜態數據參考,在實際開發中,我實際的開發邏輯為下面的 條
- 初始化調用列表數據,通過map方法為每一條數據增加一個isEdit屬性,值為false;增加一個originalData記錄需要變更的字段或者如上所示,在interface中聲明一個originalData可選屬性,在編輯數據時,再進行復制
- 點擊編輯,將isEdit值改為true
- 保存操作,給接口傳參,將修改的值進行本地賦值,如愛好下拉框選項卡,實際開發中顯示的都是Desc字段,需要進行處理。保存后,不調用列表接口,否則,就無法實現多行編輯
- 取消操作,一定要把原始值進行賦值,否則點擊編輯時,顯示的數據為編輯后未保存的值。
- 分頁切換,展示為初始化狀態,只需要正常調用接口即可。
實現效果如下圖所示:
希望上述內容對你實現類似功能有所幫助。如果你有更優的實現方法或遇到了其他問題,歡迎在評論區留言分享,我們可以一起探討優化方案。