共计 2341 个字符,预计需要花费 6 分钟才能阅读完成。
问题背景
最近在后台管理项目中,需求是需要在 A 弹窗中有个 table 表格和按钮,点击查询按钮 B 弹窗弹出,里面内容还是 table 表格,选择 B 弹窗中的 table 表格某些项,保存之后会把已选中的表格项带到 A 弹窗中。A 弹窗中再次点击查询按钮,B 弹窗此时 table 表格应该回显之前选中项。
遇到的问题,就是再次进入 B 弹窗的 table 表格未回显之前选中的某些表格项。通过排查原因是,打开 B 弹窗时候需要每次请求接口,获取表格数据,导致对象引用不同,所以使用 el-table 的 toggleRowSelection() 选中方法无效。
失效原因
1. DOM 渲染未完成
每次请求接口,数据更新后 DOM 会注销新建,导致我们勾选操作失效;可能是 table 表格相关的 DOM 渲染还未完成,无法调用 toggleRowSelection() 方法,可以使用 nextTick
解决。
2. 数据源不符
数据源问题,我们每次请求回来的表格数据,即便数据一模一样,数据对象存储地址的指针不同也会导致失败。
toggleRowSelection 需要接收表格数据中的一项。如果传递的 row 对象与 el-table 的数据源不一致,方法将无法正确选中或取消选中行。
解决方法
1. 使用 nextTick,目的是获取更新后的 DOM 元素
官方对其的定义:
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
2. 使用唯一标识符,确保数据对象一致性
可以维护一个 selectedRowIds
的集合来追踪选中的行,并在数据刷新后再重新选中这些行,主要看下 B 弹窗的代码:
template>
el-dialog v-model="modelValue" title="选择数据" width="800" :before-close="onClose">
el-table ref="tableRef" :data="state.tableList" @selection-change="onSelectionChange">
el-table-column type="selection" width="50" />
el-table-column property="项目名称" label="projectName" width="150" />
el-table-column property="推荐分行" label="branchCode" width="100" />
/el-table>
/el-dialog>
/template
script setup lang="ts">
import { ref, reactive, watch, nextTick } from 'vue'
import type { TableInstance }from 'element-plus'
const emit = defineEmits(['update:modelValue', 'select-rows'])
const onClose = () => {
emit('update:modelValue', false)
}
interface Props {
modelValue: boolean
branchCode: string
year: number
pushData: any
}
const state = reactive({
tableList: [],
selectionList: [] as any[],
selectionedRowIds: new Set(),
})
watch(
() => props.modelValue,
(val) => {
if (val) {
handleData()
}
}
)
const tableRef = refTableInstance>()
const setDefaultCheckedKeys = (rows: TableRow[] | undefined) => {
if (!rows) return
rows.forEach((row: anyObj)) =>{
if(state.selectionedRowIds.has(row.loanId)){
nextTick(()=>{
tableRef.value!.toggleRowSelection(row,true)
})
}
}
}
async function handleData(){
try {
state.tableList = data?.data??[]
state.selectionedRowIds.clear()
props.pushData.forEach(item =>{
state.selectionedRowIds.add(item.loanId)
})
setDefaultCheckedKeys(state.tableList)
}catch(error){
console.log(error)
}
}
cosnt onSelectionChange = (selection:[]) =>{
state.selectionList = selection
}
/script >
关键点
- 使用
selectedRowIds
:在数据刷新前后,使用唯一标识符来管理选中的行。- 表格数据刷新之后,遍历表格数组,和
selectedRowIds
存储的值作比较,如果存在说明是之前已选中的项;调用tableRef.value!.toggleRowSelection(row, true)
设置选中项。- 确保
tableRef.value
的有效性:在进行选中操作前,确保 tableRef.value 是有效的;使用 nextTick 确保 Dom 元素更新完毕。
通过这些方法,可以确保即使数据源更新,表格中的选中状态也能正确恢复。
参考:toggleRowSelection 失效原因及解决思路
原文地址: el-table 中 toggleRowSelection 选中方法不生效附解决方案