VUE3 EL-TABLE切换单选多选时scope的插槽等会出现渲染错误

VUE3 EL-TABLE切换单选多选时scope的插槽等会出现渲染错误
<template>
<el-table
    :data="tableData"
    row-key="id"
    @selection-change="handleSelectionChange"
    @current-change="tableCurrentChange"
    ref="multipleTable"
    highlight-current-row>
        <!-- 多选框 -->
        <el-table-column type="selection" width="55" align="center" fixed="" v-if="checked"></el-table-column>
        <!-- 自定义加载表格列 -->
        <el-table-column type="index" label="序号" width="50" align="center" fixed="left"/>
        <el-table-column prop="id" label="主键" width="110"  show-overflow-tooltip sortable v-if="false"/>
        <el-table-column prop="bookingState" label="订舱" width="70" show-overflow-tooltip sortable align="center" fixed="left">
          <template #default="scope"> 
            <el-tag type="info"  effect="dark" v-if="scope.row.bookingState=='无'"> 无 </el-tag>
            <el-tag type="warning" effect="dark" v-else-if="scope.row.bookingState=='正操作'"> 正操作 </el-tag>
            <el-tag type="success" effect="dark" v-else-if="scope.row.bookingState=='已完成'"> 已完成 </el-tag>
          </template>
        </el-table-column>
</el-table>
</template>
<script lang="ts" setup name="airOut">
  //引用省略...

  const loading = ref(false);
  const tableData = ref<any>([]);
  const checked = ref(false);

//切换单选多选
const changeChecked=()=>{
  	//清空单选选中框
    multipleSelection.value = undefined;
    //清空单选选中的数据(单选数据在多选数据数组中)
    //cargoCurrent.value = null;
    //清空多选选中的数据
    multipleSelection.value = [];
    //清空单选(清空单选选项及其单选样式)
    multipleTable.value.setCurrentRow();
    //清空多选(//清空多选选项及其多选框选择项)
    multipleTable.value.clearSelection();
}
</script>

我是用v-if来控制切换单选与多选状态,而在此之前,如是否订舱字段,使用了scope插槽对数据再次进行处理,若我切换单选多选状态,会出现表格数据渲染错位/缺失等异常情况。

最终解决方案:

在切换单选多选时,改变表格绑定的KEY并强制改变值实现重新渲染。

//切换单选多选
const changeChecked=()=>{
  	//清空单选选中框
    multipleSelection.value = undefined;
    //清空单选选中的数据(单选数据在多选数据数组中)
    //cargoCurrent.value = null;
    //清空多选选中的数据
    multipleSelection.value = [];
    //清空单选(清空单选选项及其单选样式)
    multipleTable.value.setCurrentRow();
    //清空多选(//清空多选选项及其多选框选择项)
    multipleTable.value.clearSelection();
    //强制刷新el-table表格
    tableKey.value++;
}

deepseek解题思路:

一、问题核心原因

1. 组件复用导致的渲染错乱
当使用 v-if 控制表格列的显隐时,Vue 会触发 el-table 的完整重渲染。由于 el-table 内部的行数据索引(scope.index)或虚拟 DOM 复用机制未及时更新,导致插槽内容与行数据错位关联‌。

2. 响应式依赖断裂
scope.row 的响应式依赖链可能在列切换时被破坏(如 bookingState 属性未被深度监听),导致插槽模板无法正确追踪数据变化‌。

二、解决方案(任选其一)

方案1:强制刷新表格Key
为 el-table 添加唯一标识 key,在切换多选框时强制刷新表格实例,避免复用旧渲染树。

<el-table 
  :data="tableData" 
  :key="tableKey"  <!-- 关键点 -->
>
  <el-table-column 
    v-if="checked" 
    type="selection" 
    width="55"
  ></el-table-column>
  
  <el-table-column prop="bookingState" label="订舱">
    <template #default="scope">
      <!-- 标签渲染逻辑 -->
    </template>
  </el-table-column>
</el-table>

<script setup>
const checked = ref(true);
const tableKey = ref(1);

// 切换多选框时触发
const toggleCheck = () => {
  checked.value = !checked.value;
  tableKey.value++;  <!-- 强制刷新 -->
};
</script>

优势‌:彻底解决 DOM 复用导致的错位问题‌12。


方案2:用v-show替代v-if
通过 CSS 隐藏列而非销毁组件,保留表格内部状态一致性。

<el-table-column 
  type="selection" 
  width="55" 
  v-show="checked"  <!-- 替换v-if -->
></el-table-column>

注意‌:需配合 <style> 覆盖 ElementUI 默认样式(部分版本隐藏列仍占用布局空间):

.el-table .hidden-column { 
  display: none !important; 
}

适用场景‌:需要保留勾选状态的场景‌23。


方案3:插槽内容动态Key绑定
为插槽内的 el-tag 添加与行数据关联的 key,确保内容更新触发重新渲染。

<template #default="scope">
  <el-tag 
    :key="scope.row.id + '_tag'"  <!-- 动态唯一Key -->
    :type="getTagType(scope.row.bookingState)"
  >
    {{ scope.row.bookingState }}
  </el-tag>
</template>

优势‌:精准控制插槽内容更新,避免局部渲染错位‌14。


操作验证流程

  1. 在 Vue Devtools 中检查 scope.row 数据是否与当前行匹配
  2. 监听 el-table 的 @selection-change 事件,确认勾选状态与数据关联性
  3. 使用 console.log(scope.$index) 输出行索引,观察切换列时的索引变化‌1

方案选择建议

方案适用场景风险点
强制Key刷新频繁切换且数据量大的场景可能引发短暂性能损耗
v-show替代需保留勾选/滚动条位置的场景需处理隐藏列布局问题
插槽Key绑定局部渲染异常的补充方案需确保行数据有唯一标识字段