修身养性,知行合一

  • 首页
  • 爱码
    • 系统
    • 数据库
    • JavaScript
    • CSharp
    • Python
  • 生活
    • 文化
    • 美食
  • 杂谈
  • 关于
修身养性,知行合一
码字,杂谈
  1. 首页
  2. 爱码
  3. 前端
  4. JavaScript
  5. 正文

vue 的递归插槽穿透

2025年10月10日 10点热度 0人点赞 0条评论

在二次封装 ElementUI 的 Table 时,我希望可以通过配置的方式,来实现多层表头,思路很简单,直接递归表头即可:

<!-- MyTable -->
<el-table>
  <template v-for="h in headers">
    <MyTableColumn :key="h.prop" :header="h">
      <template v-slot="scope">
        <slot :name="h.prop" v-bind="scope" />
      </template>
    </MyTableColumn>
  </template>
</el-table>
<!-- MyTableColumn -->
<template>
  <!-- 多层 -->
  <el-table-column v-bind="header" v-if="header.children && header.children.length > 0">
    <template v-for="h in header.children">
      <!-- 递归多层 -->
      <MyTableColumn :key="h.prop" :header="h" v-if="h.children && h.children.length > 0">
        <template v-slot="scope">
          <slot :name="h.prop" v-bind="scope" />
        </template>
      </MyTableColumn>

      <el-table-column v-else :key="h.prop" v-bind="h">
        <template v-slot="scope">
          <slot :name="h.prop" v-bind="scope" />
        </template>
      </el-table-column>
    </template>
  </el-table-column>

  <!-- 单层 -->
  <el-table-column v-bind="header" v-else>
    <template v-slot="scope">
      <slot :name="h.prop" v-bind="scope" />
    </template>
  </el-table-column>
</template>

<script>
export default {
  name: "MyTableColumn",
  props: {
    header: Object
  }
}
</script>

然后,直接使用:

<MyTable :headers="[
  { label: 'column-1', prop: 'a' },
  { label: 'column-2', children: [
    { label: 'column-2-1', prop: 'a-1' },
    { label: 'column-2-2', children: [
      { label: 'column-2-2-1', prop: 'a-1-1' },
      { label: 'column-2-2-1', prop: 'a-1-2' }
    ]}
  ]},
  { label: 'column-3', prop: 'c' },
  { label: 'column-4', prop: 'd' },
]">
  <template v-slot:a-1-1="{ row }">
    <span>{{ row.data }}</span>
  </template>
</MyTable>

此时会发现插槽并没有正确传递到 MyTableColumn 组件中。

为了实现插槽内容,我们需要调整一下封装的插槽内容逻辑,并不能单单的使用 <slot :name="h.prop" v-bind="scope" /> 这样的方式,而需要将所有插槽全部传递过去:

<template
  v-for="slotName in Object.keys($scopedSlots)"
  v-slot:[slotName]="slotData"
>
  <slot :name="slotName" v-bind="slotData || {}" />
</template>

我们把所有在递归时使用插槽的地方都用上面的内容替换掉:

<!-- MyTable {L5-L11} -->
<el-table>
  <template v-for="h in headers">
    <MyTableColumn :key="h.prop" :header="h">
      <!-- 传递所有作用域插槽给 TableColumn -->
      <template
        v-for="slotName in Object.keys($scopedSlots)"
        v-slot:[slotName]="slotData"
      >
        <slot :name="slotName" v-bind="slotData || {}" />
      </template>
    </MyTableColumn>
  </template>
</el-table>
<!-- MyTableColumn -->

<!-- ... other codes -->
<!-- 递归多层 -->
<MyTableColumn :key="h.prop" :header="h" v-if="h.children && h.children.length > 0">
  <!-- 传递所有作用域插槽给 TableColumn -->
  <template
    v-for="slotName in Object.keys($scopedSlots)"
    v-slot:[slotName]="slotData"
  >
    <slot :name="slotName" v-bind="slotData || {}" />
  </template>
</MyTableColumn>
<!-- ... other codes -->

此时再尝试效果,发现就正常了。通过 Object.keys($scopeSlots) 的方式,可以将插槽带到每一个需要的层级去。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可
标签: vue
最后更新:2025年10月10日

jeremyjone

这个人很懒,什么都没留下

打赏 点赞
< 上一篇

文章评论

取消回复

最新 热点 随机
最新 热点 随机
vue 的递归插槽穿透 Github Pages SPA 重定向 行间距引出的 DOCTYPE 怪异行为 写个小彩蛋 绘制一个可重用的线条阴影 node-sass 的安装
Github Pages SPA 重定向vue 的递归插槽穿透
将flask程序部署在apache上 iOS 正则匹配问题 JavaScript数字和字符互转 将 .net core 项目部署到 Linux(含配置多个项目) IdentityServer4深入使用(二)-- 认证与授权(下) vue 的递归插槽穿透

(っ•̀ω•́)っ✎⁾⁾ 开心每一天

COPYRIGHT © 2021 jeremyjone.com. ALL RIGHTS RESERVED.

THEME KRATOS MADE BY VTROIS

京ICP备19012859号-1

京公网安备 11010802028585号