el-table 表格里 header的插槽可能导致插槽内内容不能正常进行响应式更新

260 阅读1分钟

在公司一个vue2项目中偶然发现有一个el-table的表头slot里的按钮控制和表格里行数据的按钮控制结果不一致。 代码片段如下:

 <el-table-column width="80" v-if="isAfter">
              <template slot="header">
                <el-button
                  :disabled="disabled || !editAbleProp.includes('3')"
                  @click="handleAddYtMx"
                  size="mini"
                  >新增</el-button
                >
              </template>
              <template slot-scope="{ row, $index }">
                <el-popconfirm title="确定删除吗?" @confirm="handleDelYtMx(row, $index)">
                  <el-button
                    slot="reference"
                    :disabled="disabled || !editAbleProp.includes('3')"
                    type="danger"
                    size="mini"
                    >删除</el-button
                  >
                </el-popconfirm>
              </template>
            </el-table-column>

这里两个按钮用了同样的控制逻辑,但最终结果却是一个被禁用,一个放开,很奇怪。 问了gpt后给了答案。

当使用slot="header"来定义表头时,Vue会将其视为静态内容,即在编译阶段就确定了其内容,不会进行响应式更新。这是因为Vue在编译模板时,会对静态内容进行优化,将其提升为静态的渲染结果,以提高性能。 而使用#header的方式,是Vue的一种特殊语法,它会将表头内容作为一个动态插槽处理。动态插槽会被Vue处理为响应式的内容,当数据变化时,Vue会重新渲染插槽内容,并将其更新到对应的位置上。这样就实现了自动更新。 简单来说,静态内容在编译阶段就确定了,不会进行响应式更新。而动态插槽是Vue的一种特殊语法,会被处理为响应式的内容,可以实现自动更新。所以,如果需要在表头中使用变量,并希望实现自动更新,建议使用动态插槽#header的方式来定义表头内容。

于是把slot="header" 改为 #header后问题成功解决。