细致讲解slot插槽的使用

细致讲解slot插槽的使用彻底搞懂 slot 插槽 图文详解 1 什么是插槽 Vue 实现了一套内容分发的 API 将 元素作为承载分发内容的出口 插槽实质是对子组件的扩展 通过 插槽向组件内部指定位置传递内容 slot 的出现是为了父组件可以堂而皇之地在子组件中加入内容 插槽显不显示 怎样显示是由父组件来控制的 而插槽在哪里显示就由子组件来进行控制 2 slot 与 props 的区别 3 插槽的使用 1 匿名插槽 单个插槽 默认插槽 2 具名插槽 3 作用域插槽因为父级模板里的所有内容都是在父级作用域中编译的 子级模板里的所有内容

1、什么是插槽

VUE官方文档的解释:

Vue 实现了一套内容分发的 API,将
元素作为承载分发内容的出口。

个人理解:

插槽实质是对子组件的扩展,通过
插槽向子组件内部指定位置传递内容。

或者这么说:


的出现是为了父组件可以堂而皇之地在子组件中加入内容。

打个比方:

有句话叫一个萝卜一个坑。父组件想要在子组件中种萝卜,需要在子组件中挖个坑,
就是一个【萝卜坑】。父组件想要给子组件添加的内容就是【萝卜】。

由此可见,萝卜种不种,种什么萝卜由父组件控制;萝卜坑在哪,由子组件控制。 换言之 ——

插槽显不显示、怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制。

举个栗子,在 Father 父组件内部使用名为 Child 的子组件,向子组件的内部的“指定位置”传递一些内容,你可以这么写:

<!-- 这是子组件--> <div class="child"> <h2>Child的标题</h2> <slot>我是一个萝卜坑</slot> </div> 
<!-- 这是父组件--> <div class="father"> <h1>Father的标题</h1> <Child> 我是个萝卜~ </Child> </div> 

看到没,是不是就像父组件的萝卜种到了子组件的坑里

看到这里不禁发出灵魂一问:这不就是父组件给子组件传了个值吗?那和props有啥区别?

2、与 props 的区别

通过props属性,父组件只能向子组件传递属性、方法
<template> <div> <h1>我是A</h1> <child :to-child-data="parentData" :to-child-fun="parentFun"></child> </div> </template> <script> import child from './B.vue' export default { 
    name:'A', components: { 
    child }, data () { 
    return { 
    say: '', parentData: "hello" }; }, methods: { 
    parentFun(val) { 
    //自定义的函数 val是子组件给的参数 this.say = val; //献给data一份问候~ console.log(val," from child"); //看看参数有没有值 console.log(this.say," from parent"); //看看能不能给父组件的data传进去 }, } }; </script> 
<template> <div> <h2>我是B</h2> <el-button @click="childClick">子组件调用父组件的props方法</el-button> </div> </template> <script> export default { 
    name:'B', data () { 
    return { 
    }; }, props: { 
    toChildFun: { 
    type: Function, //参数类型:函数 required: true //是否必填:是 }, toChildData: { 
    type: String, //参数类型:String default: '' //默认值 } }, methods: { 
    childClick(event) { 
    this.$props.toChildFun('这是来自子组件的问候~~'); //调用Props传来的方法,并送他一个参数~~ // this.toChildFun('这是来自子组件的问候~~'); //跟上面一个效果 } } }; </script> 

在这里插入图片描述在这里插入图片描述

而插槽还可以传递带标签的内容、甚至是组件:
<!-- 这是父组件哦--> <div class="father"> <h1>Father的标题</h1> <Child> { 
   { 
   username}} <!-- 参数--> <button>我是一个按钮</button> <!-- 带标签的内容--> <Child2></Child2> <!-- 组件--> </Child> </div> 

3、插槽的使用

(1)匿名插槽(又叫单个插槽、默认插槽)

就是没有设置name属性的插槽。

<slot>这是个匿名插槽(没有name属性),这串字符是匿名插槽的默认值。</slot> 
<div class="child"> <h1>子组件</h1> <slot name="head">头部默认值</slot> <slot name="body">主体默认值</slot> <slot>这是个匿名插槽(没有name属性),这串字符是匿名插槽的默认值。</slot> </div> 
<div class="parent"> <h1>父组件</h1> <child> <p slot="body">我是主体</p> <p>我是其他内容</p> <p slot="footer">我是尾巴</p> </child> </div> 

注意:

1、

我是尾巴

插槽被丢弃了,因为子组件中没有

的插槽与之匹配。

2、 如果子组件中的匿名插槽不存在,则

我是其他内容

也会被丢弃。

这个例子就是想说明两点:

1、坑会一直在,但是没有找到坑的萝卜就会被丢弃!
2、后来者居上,后面的萝卜会覆盖原来坑里的萝卜

(2)具名插槽

意思就是具有名字的插槽,名字通过属性name来定义。

<slot name="body">这是个具名插槽(有name属性),这串字符是具名插槽的默认值。</slot> 

一个组件中可以有很多具名插槽,出现在不同的位置。

<!-- <base-layout>组件--> <div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> <!-- 一个不带 name 的 <slot> 出口会带有隐含的名字“default”。--> </main> <footer> <slot name="footer"></slot> </footer> </div> 

上面的那个例子,是直接把slot直接用在普通标签或者
上:

我是主体

出资之外, 更推荐在
元素上使用 v-slot 指令
,并以 v-slot 的参数的形式提供插槽名称,这样就可以定义插槽的内容了:

等于

插槽内容

<base-layout> <template v-slot:header> <h1>我是头header</h1> <!-- <h1 slot="header">我是头header</h1>--> </template> <p>我是main的内容111</p> <p>我也是main的内容222</p> <template v-slot:footer> <p>我是footer</p> <!-- <p slot="footer">我是footer</p>--> </template> </base-layout> 

1、带有 v-slot 的
元素中的所有内容都将会被传入相应的插槽。
2、任何没有被包裹在带有 v-slot 的
中的内容都会被视为默认插槽的内容。

如果你希望更明确一些,可以在一个
中包裹默认插槽的内容:

<base-layout> <template v-slot:header> <h1>我是头header</h1> </template> <template v-slot:default> <p>我是main的内容111</p> <p>我也是main的内容222</p> </template> <template v-slot:footer> <p>我是footer</p> </template> </base-layout> 

以上两种写法的渲染效果是一样的:

注意:slot 可以用在任何元素上,v-slot 只能添加在
上。
只有一种例外情况,请继续往下看。

(3)作用域插槽

上面props的例子,可以看到 父组件传给子组件了一个属性和一个方法,子组件可以使用 props 中的属性和方法。那对于插槽来说,父组件想访问子组件的数据,又该怎么做呢?

<!-- 这是子组件<Child> --> <template> <div> <h1>hey,我是组件Child的标题</h1> <slot></slot> </div> </template> <script> export default { 
          data() { 
          return { 
          childUser: { 
          Name:"Tom", Age: 23 } } } </script> 

当Father使用Child组件时,想访问Child中的数据 childUser 并且将其展示在插槽的位置:

<!-- 这是父组件<Father>--> <div> <h1>hey,我是父组件Father的标题</h1> <Child> { 
         { 
         childUser.Name}} </Child> </div> 

然而上述代码不会正常工作,因为

父级模板里的所有内容都是在父级作用域中编译的;子级模板里的所有内容都是在子作用域中编译的。

只有
组件可以访问到 childUser,而我们提供的内容【childUser.Name、childUser.Age】是在父级
中渲染的。

为了让 childUser 在父级的插槽内容中可用,需要把 childUser 从

子级作用域传递到
父级作用域

做法就是将 childUser 作为
元素的一个属性绑定上去:

 
          <template> <div> <h1>hey,我是组件Child的标题 
           h1> <slot v-bind:childData="childUser"> 
            slot>  
             div>  
              template> <script> export default { 
                data() { 
                return { 
                childUser: { 
                Name:"Tom", Age:23 } } }  
               script> 
绑定在
元素上的属性childData 被称为插槽 prop。
现在,在父级作用域中,我们可以使用带值的 v-slot 来定义 插槽 prop 的名字:
 
          <div> <h1>hey,我是父组件Father的标题 
           h1> <Child> <template v-slot:default="slotProps"> { 
         { slotProps.childData.Name}} { 
         { slotProps.childData.Age}}  
            template>  
             Child>  
              div> 
在这个例子中,我们将[ 包含所有插槽 prop 的对象 ] 命名为 slotProps(自定义)。

因为在上述情况下(这里就是上面说的那一种例外情况),被提供的内容只有默认插槽,组件的标签可以被当作插槽的模板来使用。这样我们就可以把 v-slot 直接用在组件上:

 
          <div> <h1>hey,我是父组件Father的标题 
           h1> <Child v-slot:default="slotProps"> { 
         { slotProps.childData.Name}} { 
         { slotProps.childData.Age}}  
            Child>  
             div> 

还可以省略default。就像未指明的内容对应默认插槽一样,不带参数的 v-slot 被假定对应默认插槽:

 
          <div> <h1>hey,我是父组件Father的标题 
           h1> <Child v-slot="slotProps"> { 
         { slotProps.childData.Name }} { 
         { slotProps.childData.Age}}  
            Child>  
             div> 
但是默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确:
 
          <Child v-slot="slotProps"> { 
        { slotProps.childData.Name }} <template v-slot:other="otherSlotProps"> slotProps is NOT available here  
           template>  
            Child > 

只要出现多个插槽,请始终为所有的插槽使用完整的基于
的语法:

也就是说,但只要出现多个插槽,所有的插槽名都得写全了,不能省略。

 
          <template> <div> <h1>hey,我是组件Child的标题 
           h1> <slot v-bind:childData="childUser"> 
            slot>  
            <slot name="other" v-bind:otherChildData="otherChildUser"> 
             slot>  
              
              div>  
               template> <script> export default { 
                 data() { 
                 return{ 
                 childUser: { 
                Name:"Tom",Age:23}, otherChildUser:{ 
                Name:"Mike",Age:25} } }  
                script> 
 
          <Child > <template v-slot:default="slotProps">  
          { 
        { slotProps.childData.Name }}  
           template> <template v-slot:other="otherSlotProps"> { 
         {otherSlotProps.otherChildData.Name}}  
            template>  
             Child> 
上面v-bind:childData="childUser",是将 childUser 作为
元素的一个属性绑定上去,感觉起的名太多了,有点眼花缭乱了,还能再简洁一点:
v-bind: 后面的参数是可以省略的:

在这里插入图片描述

 
          <div> <h1>hey,我是组件Son的标题 
           h1> <slot v-bind="childUser"> 
            slot>  
             
             div> 
 
          <div> <h1>hey,我是父组件Father的标题 
           h1> <Son> <template v-slot:default="user">  
           { 
         { user.Name}}, { 
         { user.Age}}  
            template>  
             Son>  
              div> 

还可以省略的defalut:

 
          <div> <h1>hey,我是父组件Father的标题 
           h1> <Son> <template v-slot="user">  
           { 
         { user.Name}}, { 
         { user.Age}}  
            template>  
             Son>  
              div> 

(4)解构插槽 Prop

作用域插槽的内部工作原理是将你的插槽内容包裹在一个拥有单个参数的函数里

所以,这意味着 v-slot 的值实际上可以是任何能够作为函数定义中的参数的 JavaScript 表达式。这样就很灵活。

 
          <template> <div> <h1>hey,我是组件Child的标题 
           h1> <slot v-bind="childUser"> 
            slot>  
             
             div>  
              template> <script> export default { 
                data() { 
                return { 
                childUser: { 
                Name:"Tom", Age:23 } } }  
               script> 
 
          <Child v-slot="{user}"> { 
        { user.Name }}  
           Child> 

还可以将 user重命名为 person:

 
          <Child v-slot="{ user: person }"> { 
        { person.Name }}  
           Child > 

甚至可以定义默认内容,用于插槽 prop 是 undefined 的情形:

 
          <Child v-slot="{ user= { Name: 'Guest' } }"> { 
        { childData.Name }}  
           Child > 

对象的解构赋值看不明呗的请移步 ====>> 变量的解构赋值—ES6入门,第六节。

4、v-slot 、 slot 、 slot-scope

(1) slotslot-scope 已经被废弃
(2) 所有的 2.x 版本中, slotslot-scope 属性仍会被支持
(3) Vue 3 不支持 slotslot-scope所以更推荐使用 v-slot

其实,v-slot就是把 slot 和 slot-scope 的功能整合了一下,把两个人的活都干了


v-slot 的使用

1、在一个
元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称。

%ignore_pre_29%

2、只有 当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。 这样我们就可以把 v-slot 直接用在组件标签上。除此之外,v-slot 必须用在
元素上。

%ignore_pre_30%
%ignore_pre_31%

也就是说,如果你希望使用缩写的话,#后面必须写插槽名,default不可以省略

%ignore_pre_32%

再来复习一下省略default:

%ignore_pre_33%

slot 、 slot-scope 的使用

<template> <div> <h1>这里是子组件 
            h1> <slot name="mySlot" v-bind="childUser">  
             slot>  
              div>  
               template> <script> export default { 
                 name: 'Son', data() { 
                 return { 
                 childUser: { 
                 Name: "Tom", Age: 23 } } } }  
                script> 
<div> <h1>hey,我是父组件Father的标题 
            h1> <Son> <div slot="mySlot" slot-scope="data"> { 
          { data.Name }} { 
          { data.Age }}  
             div>  
              Son>  
               div> 

1、 slot=“default” 可以省略不写,slot可以用在
元素,也可以用在任意的普通元素上。

2、这里的 slot-scope 声明了被接收的 prop 对象会作为 slotProps 变量存在于
作用域中。你可以像命名 JavaScript 函数参数一样随意命名 slotProps。同样的,slot-scope可以用在 template元素,也可以用在任意的普通元素上。

5、进阶

在循环中使用slot插槽时的传值方法、组件中遍历插槽

确定不点个赞再走?

欢迎交流讨论~







版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/201000.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月20日 上午10:09
下一篇 2026年3月20日 上午10:09


相关推荐

  • Android面试题总结【完整详细版本”一”】(含答案)

    Android面试题总结【完整详细版本”一”】(含答案)1、四大组件是什么?Activity【活动】:用于表现功能。 Service【服务】:后台运行服务,不提供界面呈现。 BroadcastReceiver【广播接收器】:用来接收广播。 ContentProvider【内容提供商】:支持在多个应用中存储和读取数据,相当于数据库。2、四个组件的生命周期?Activity生命周期图及Fragment生命周期图…

    2022年5月11日
    45
  • strncmp函数用法是什么

    strncmp函数用法是什么strncmp 函数用法 函数原型 intstrcmp char str1 char str2 intn 功能比较字符串 str1 和 str2 的前 n 个字符 头文件 include 返回值

    2026年3月26日
    2
  • 表白代码Python_自制表白神器

    表白代码Python_自制表白神器文章目录前言演示网站制作部署网站二维码制作总结前言跟着我做,不要跳着看,否则你会失败。第一步是制作二维码;第二步是制作网站。演示具体成果地址:https://yanghanwen.xyz/ai/网站制作首先你需要下载我的这个完整项目:链接:https://pan.baidu.com/s/1EmRehx_gRnT5hLjJvKuAIg提取码:pz1y–来自百度网盘超级会员V2的分享下载好后文件目录如下:然后你需要注意的是我把img里面的图片删了,涉及隐私,大家自己替换自己追

    2022年8月23日
    11
  • 国内如何使用谷歌(google)搜索引擎进行搜索?

    国内如何使用谷歌(google)搜索引擎进行搜索?1.可先更新浏览器到最新版本,目前最新V98版本【谷歌浏览器】,密码33602.到【访问助手插件】下载插件,密码同上,下载谷歌访问助手插件。3.地址栏输入chrome://extensions。将

    2022年7月3日
    79
  • 默认网关 计算机网络_计算机网络默认网关

    默认网关 计算机网络_计算机网络默认网关什么是网关?  大家都知道,从一个房间走到另一个房间,必然要经过一扇门。同样,从一个网络向另一个网络发送信息,也必须经过一道“关口”,这道关口就是网关。顾名思义,网关(Gateway)就是一个网络连接到另一个网络的“关口”。按照不同的分类标准,网关也有很多种。TCP/IP协议里的网关是最常用的,在这里我们所讲的“网关”均指TCP/IP协议下的网关。  网关实质上是一个网络通向其他网络的IP地址…

    2025年7月13日
    3
  • Production-Ready Beanstalkd with Laravel 4 Queues

    Production-Ready Beanstalkd with Laravel 4 Queues

    2021年8月29日
    58

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号