查看: 265|回复: 0

Vue中Slot具名插槽与default作用域插槽用法教程

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
插槽 Slot 是 Vue 框架自带的核心特性,并不是 Element Plus 这类组件库的专属能力。它解决的是组件内容分发和自定义的问题:任何一个 Vue 组件,无论业务组件还是第三方组件库,都可以预留插槽,由使用方在组件外部决定某一块区域渲染什么。

实际使用中,最容易混淆的是 #footer 和 #default="scope" 这两种写法,下面拆开说明。

一、#footer 是具名插槽

具名插槽的含义非常直接:组件内部存在一个带名字的插槽出口,例如 <slot name="footer"></slot>。使用方想在具体位置填充内容时,必须通过 #footer 或 v-slot:footer 来指明自己写的内容要放到哪个具名插槽里。

Element Plus 的 el-dialog 组件中,footer 插槽用来定制弹窗底部的按钮区域。如果不使用具名插槽,弹窗默认不会有自定义底部,而使用 #footer 就能完全接管底部按钮结构。
  1. <template #footer>
  2.   <div class="dialog-footer">
  3.     <el-button type="primary" @click="confirm(formRef)">
  4.       确认
  5.     </el-button>
  6.   </div>
  7. </template>
复制代码

这里的 #footer 本质上是 v-slot:footer 的简写。它只负责把内容填充到组件预先定义好的位置,接收不到组件内部传出的业务数据,所以适合做静态或自定义逻辑的内容。

二、#default="scope" 是默认插槽加作用域插槽

#default 表示默认插槽,也就是组件内部没有设置 name 的那个 <slot></slot>。

="scope" 的部分表示接收组件向插槽外部传递的数据。也就是说,组件不只是让使用方传内容进去,还会把自身内部的数据通过插槽传出来。

Element Plus 中 el-table-column 的自定义列经常这样写:
  1. <el-table-column label="操作">
  2.   <template #default="scope">
  3.     <button @click="open(scope.row)">编辑</button>
  4.   </template>
  5. </el-table-column>
复制代码

这里的 scope 是模板中声明的一个对象,通过插槽数据链路拿到组件内部暴露出来的字段。在表格场景下,scope.row 就是当前行的数据,所以按钮可以拿到当前行进行编辑或其他操作。

完整写法原本是 v-slot:default="scope",默认插槽允许省略 default,所以写作 #default="scope";如果不想写 default,直接使用 #="scope" 也是被 Vue 支持的。

为了把原理看透,再看一个自建的子组件例子。子组件内部这样暴露数据:
  1. <slot :name-list="nameList"></slot>
复制代码

父组件使用时通过作用域插槽接收子组件传出的数据:
  1. <my-component>
  2.   <template #default="slotProps">
  3.     <span>{{ slotProps.nameList }}</span>
  4.   </template>
  5. </my-component>
复制代码

这里 #default 指向子组件中没有 name 的 <slot>,slotProps 接收子组件通过插槽属性传出来的 nameList,从而实现子组件数据到父组件模板的流动。

三、什么时候必须用 template 包裹

如果只是普通默认插槽,没有具体插槽名,也不需要接收数据,那么可以直接把内容写在组件标签内部,不需要再套一层 template:
  1. <!-- 子组件定义 -->
  2. <div class="my-component">
  3.   <slot></slot>
  4. </div>
  5. <!-- 父组件使用 -->
  6. <my-component>
  7.   <p>这是默认插槽的内容</p>
  8. </my-component>
复制代码

如果使用具名插槽,则必须有 template,否则 Vue 不知道内容要放到哪个插槽位置。像上面的 #footer,必须写成:
  1. <template #footer>
  2.   <el-button>确认</el-button>
  3. </template>
复制代码

如果使用作用域插槽,同样必须有 template。原因是作用域插槽接收的数据,需要声明在 template 标签的指令上,没有 template 就没有地方声明接收变量:
  1. <template #default="scope">
  2.   <button @click="open(scope.row)">编辑</button>
  3. </template>
复制代码

四、两者本质区别归纳

具名插槽,例如 #footer,解决的是“内容放在组件哪个预设位置”的问题。它通常不关心组件内部状态,只要填充到指定区域,常用于弹窗底部、卡片头部等固定位置的定制。

默认插槽加作用域插槽,例如 #default="scope",解决的是“组件主要内容如何借助内部数据动态渲染”的问题。使用方必须接收组件传出的数据,再基于这些数据拼接界面,常用于表格列、列表项、下拉选项等需要拿到当前数据的场景。

对照这两种写法:#footer 是给组件的指定插槽位置塞内容,不接收数据;#default="scope" 是接收组件给的数据,再自定义组件的主要内容。

最后记住一个简单规则:默认插槽且没有数据,可以不写 template;具名插槽必须写 template;作用域插槽也必须有 template,因为要在 template 上声明作用域变量。理解这一层,以后看 Element Plus 或自建组件中的 #footer、#default="scope" 就不会再模糊了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-2 17:02 , Processed in 0.025180 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部