在项目中使用 Element UI 的 el-table 组件时,我遇到了一个问题:当来回切换不同条件展示不同的表格列时,页面会抛出如下错误:
TypeError: _self.$scopedSlots.default is not a function
这个错误主要出现在我们使用了 v-if 来动态展示不同表格列的场景下,特别是在列中使用了 slot-scope 处理内容时,频繁切换表格列会导致渲染出错。
问题分析
当使用 v-if 动态控制表格的显示或隐藏时,Vue 只是控制了元素的渲染状态,并没有完全卸载 DOM。Vue 的渲染机制倾向于复用现有的 DOM 节点,以提升性能。然而,在频繁切换条件的情况下,Vue 有时无法正确更新表格中的 slot-scope 作用域,导致 _self.$scopedSlots.default 变为未定义,从而抛出错误。
问题更容易出现在以下两种情况下:
表格中的列使用了 v-if 或 v-show 来动态展示。
列中的内容依赖于 slot-scope 来渲染,如自定义的模板内容。
解决方案
为了解决这个问题,有两种常见的做法:
方案一:为 el-table 添加 key 属性
给 el-table 添加 key 属性,确保每次切换条件时,Vue 能够识别到这是一个新的表格,强制重新渲染而不是复用旧的 DOM 节点。
<template>
<div>
<el-table :key="tableKey" v-if="showTableA" :data="tableDataA">
<el-table-column label="Name" prop="name"/>
<el-table-column label="Age" prop="age"/>
</el-table>
<el-table :key="tableKey" v-else :data="tableDataB">
<el-table-column label="Product" prop="product"/>
<el-table-column label="Price" prop="price"/>
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
showTableA: true,
tableDataA: [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }],
tableDataB: [{ product: 'Laptop', price: 1000 }, { product: 'Phone', price: 500 }],
};
},
computed: {
tableKey() {
return this.showTableA ? 'tableA' : 'tableB';
}
}
}
</script>
通过为 el-table 组件设置 key,Vue 在表格内容切换时,会将其视为不同的表格并重新渲染,而不是复用现有的 DOM 节点。
方案二:为 el-table-column 设置 key 属性
如果问题出现在列的动态渲染中,尤其是在使用 slot-scope 时,可以为 el-table-column 添加 key 属性。虽然使用 Math.random() 生成唯一 key 有时被推荐,但为了避免潜在的重复问题,建议使用列的 prop 或其他唯一标识字段生成 key。
<template>
<div>
<el-table :data="tableData">
<el-table-column :key="'name-column'" label="Name" prop="name">
<template slot-scope="scope">
<span>{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column :key="'age-column'" label="Age" prop="age">
<template slot-scope="scope">
<span>{{ scope.row.age }}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 30 }],
};
}
}
</script>
通过为 el-table-column 添加唯一的 key,确保了在渲染列时 Vue 能够准确识别并更新每一个列的状态,避免了由于 DOM 节点复用导致的渲染问题。
总结
当我们在 el-table 中使用 v-if 动态展示列并同时使用 slot-scope 进行自定义内容时,如果没有设置合适的 key,Vue 会复用 DOM 节点,从而导致 _self.$scopedSlots.default is not a function 的错误。为了解决这一问题,可以采用以下两种方案:
- 为 el-table 设置 key 属性,确保表格在切换时能够重新渲染。
- 为 el-table-column 设置唯一的 key属性,确保列的渲染和切换不会出错。
通过合理设置 key,可以避免因 DOM 节点复用导致的渲染问题,使表格动态展示功能更加稳定。