Vue.js类Excel编辑器实现单元格修改后自动更新数据库
问题描述
我希望构建一个具备Excel功能的简易编辑器,要求单元格值变更时数据自动保存至数据库。目前我的实现是编辑单元格后需点击保存按钮才能更新数据库中的值,我是新手,恳请提供帮助🙏。以下是相关代码(并非完整代码,但希望能有所帮助):
HTML 代码
<div> <v-toolbar> <v-dialog> <template #activator="{ on, attrs }"> <v-btn color="orange" dark depressed :loading="exportCSVLoader" class="mb-2 mx-2" @click="exportCSV" > 导出 </v-btn> <ImportCSV :import-c-s-v-loader="importCSVLoader" @csv-data="getImportFileData" /> <v-btn color="primary" dark depressed class="mb-2" v-bind="attrs" v-on="on" > 添加新条目 </v-btn> <v-btn dark color="red" :loading="deleteButtonLoader" depressed class="mb-2 mx-1" @click="deleteItem(deleteItemRow)" > 删除 </v-btn> <v-btn color="blue" dark :loading="saveButtonLoader" depressed class="mb-2 mx-1" @click="SaveExcelRecord(editedRow)" > 保存 </v-btn> </template> <v-card> <v-card-title> <span class="text-h5">{{ formTitle }}</span> </v-card-title> <v-divider></v-divider> <v-card-text> <v-container> <HouseTextFields :edited-item="editedItem" @clear="close" /> </v-container> </v-card-text> <v-divider></v-divider> <v-card-actions> <v-spacer></v-spacer> <v-btn color="blue darken-1" text @click="close"> 取消 </v-btn> <v-btn :loading="saveButtonLoader" color="blue darken-1" text @click="save" > {{ editedItem?.id ? '更新' : '保存' }} </v-btn> </v-card-actions> </v-card> </v-dialog> <v-dialog v-model="dialogDelete" max-width="500px"> <v-card> <v-card-title class="text-h5" >确定要删除这一行吗?</v-card-title > <v-card-actions> <v-spacer></v-spacer> <v-btn color="blue darken-1" text @click="closeDelete" >取消</v-btn > <v-btn color="blue darken-1" text :loading="deleteButtonLoader" @click="deleteItemConfirm" >确定</v-btn > <v-spacer></v-spacer> </v-card-actions> </v-card> </v-dialog> </v-toolbar> <v-divider></v-divider> </div> <vue-excel-editor ref="grid" v-model="dataItem" :new-if-bottom="false" :allow-add-col="true" :no-header-edit="true" width="100%" :localized-label="myLabels" filter-row @cell-click="onRowDataChange" @update="updateRow" @select="rowSelected" > ... </vue-excel-editor>
JavaScript 代码
methods: { updateRow(val) { if (val && val.length > 0) { let arr = [] val.forEach(row => { if (this.dataItem?.length) { this.dataItem.find(el => { if (el.$id === row.$id) { // 删除$id字段 delete el['$id'] // 格式化日期 if (el.builddate) el.builddate = moment(el.builddate).format('YYYY-MM-DD') if (el.lastrenovation) el.lastrenovation = moment(el.lastrenovation).format( 'YYYY-MM-DD' ) if (el.created_at) el.created_at = moment(el.created_at).format('YYYY-MM-DD') if (el.updated_at) el.updated_at = moment(el.updated_at).format('YYYY-MM-DD') // 添加到数组 arr.push(el) } }) } }) console.log('修改的行数据', arr) this.editedRow.data = [...arr] } }, async SaveExcelRecord() { if (!this.editedRow.data || this.editedRow.data.length === 0) { // this.initToast("没有数据需要保存。", "info"); return 'no data' } this.saveButtonLoader = true try { // 假设API支持批量更新 await axios.post( `http://127.0.0.1:8000/api/JsonBulk`, this.editedRow.data ) this.initToast('数据已更新并保存!', 'success') // 重置编辑状态 this.editedRow = { index: -1, data: [] } // 重新加载所有记录 this.getHouseRecords() this.close() } catch (error) { this.initToast('数据更新失败', 'error') } finally { this.saveButtonLoader = false } } }
解决方案
要实现单元格变更自动保存,核心是利用vue-excel-editor的@update事件,在数据修改时直接触发保存接口,同时加入防抖避免频繁请求:
步骤1:添加防抖函数
防抖可以避免用户连续修改单元格时多次调用接口,在methods中添加:
debounce(func, delay) { let timeoutId return function(...args) { clearTimeout(timeoutId) timeoutId = setTimeout(() => func.apply(this, args), delay) } }
步骤2:修改updateRow方法,自动触发保存
修改updateRow,处理完数据后直接调用保存方法,同时用防抖包装:
updateRow(val) { if (val && val.length > 0) { let arr = [] val.forEach(row => { if (this.dataItem?.length) { const el = this.dataItem.find(el => el.$id === row.$id) if (el) { // 删除$id字段 delete el['$id'] // 格式化日期 if (el.builddate) el.builddate = moment(el.builddate).format('YYYY-MM-DD') if (el.lastrenovation) el.lastrenovation = moment(el.lastrenovation).format('YYYY-MM-DD') if (el.created_at) el.created_at = moment(el.created_at).format('YYYY-MM-DD') if (el.updated_at) el.updated_at = moment(el.updated_at).format('YYYY-MM-DD') arr.push(el) } } }) console.log('修改的行数据', arr) this.editedRow.data = [...arr] // 触发自动保存,防抖300毫秒 this.debounce(() => this.SaveExcelRecord(), 300)() } }
步骤3:调整保存逻辑(可选)
如果你的API支持单条数据更新,可以单独写一个单条保存方法,减少数据传输:
async saveSingleRow(row) { this.saveButtonLoader = true try { await axios.post(`http://127.0.0.1:8000/api/JsonBulk`, [row]) this.initToast('数据已保存!', 'success') this.getHouseRecords() } catch (error) { this.initToast('保存失败', 'error') } finally { this.saveButtonLoader = false } }
然后在updateRow中调用:
// 替换原来的SaveExcelRecord调用 this.debounce(() => { arr.forEach(row => this.saveSingleRow(row)) }, 300)()
步骤4:测试效果
现在编辑单元格后,等待300毫秒(可调整延迟时间),系统会自动调用接口保存数据,无需手动点击保存按钮。
内容的提问来源于stack exchange,提问作者Maria
相关产品推荐
相关产品推荐

