Vue笔记 – 插槽(slot) 详解

Vue笔记 – 插槽(slot) 详解插槽注意:本篇笔记为方便兼容Vue3,均采用了比较新的v-slot写法,而未采用老式的slot和slot-scope插槽(slot)是vue为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽,可以把插槽认为是组件封装期间,为用户预留的内容的占位符。

大家好,欢迎来到IT知识分享网。Vue笔记

插槽

目录
  • 插槽
    • 1. 默认插槽
    • 2. 具名插槽
    • 3. 作用域插槽

注意:本篇笔记为方便兼容Vue3,均采用了比较新的v-slot写法,而未采用老式的slot和slot-scope

  • 插槽(slot)是 vue 为组件的封装者提供的能力。允许开发者在封装组件时,把不确定的、希望由用户指定的部分定义为插槽,可以把插槽认为是组件封装期间,为用户预留的内容的占位符。

  • 插槽常用于父组件向子组件指定位置插入html结构,也是一种组件间通信方式,适用于父组件→子组件

  • $slots是组件插槽集,是组件所有默认插槽、具名插槽的集合,可以用来获取当前组件的插槽集

1. 默认插槽

  • 父组件:

    <template>
    	<div class="container">
            <!--默认插槽-->
            <!--写在标签上的是父组件以props形式向子组件传递的属性,与插槽无关-->
            <Category title="美食" :listDate="foods">
                <!--希望向子组件中插入的内容-->
        		<img src="img1.jpg">
        	</Category>
        </div>
    </template>
    
    <script>
    	import Category from './components/Category'
        export default{
            name:'App',
            components:{Category}
        }
    </script>
    
  • 子组件:

    <template>
    	<div class="category">
            <slot></slot>
        </div>
    </template>
    <script>
        export default{
            name:'Category'
        }
    </script>
    
  • 解析:

    在父组件调用 子组件Category 时,额外附加了一段代码<img src="img1.jpg">。添加这段代码后,vue会在Category中自动寻找可以插入的地方。

    若Category中定义了插槽<slot></slot>,则这段代码会被替换为<img src="img1.jpg">;若没有,则父组件传入的代码会被自动抛弃

    如果在<slot></slot>之间写入代码,则该段代码将会作为后备内容。即,若父组件没有传入附加代码,该段代码会作为默认值自动渲染

  • 注意:

    • 若父组件需要传入不同的代码,并在子组件不同地方渲染,默认插槽会失效,此时需使用具名插槽

    • 默认插槽是特殊的具名插槽,它具有隐藏的name="default"

    • 默认插槽无法让父组件获取子组件中的变量和值

      <navigation-link url="/profile">
        Logged in as {{ user.name }}
      </navigation-link>
      

      此处user.name在子组件中为undefined。因为插槽会先渲染然后再传递到子组件中,而user.name在父组件中不存在,即便子组件中具有user.name,也不会获取到该变量

      如果要让父组件获取子组件中的变量和值,可以使用作用域插槽

2. 具名插槽

有时候会同时需要多个插槽,并将其渲染到不同的位置上,此时就需要使用具名插槽

  • 父组件:

    <template>
    	<div class="container">
            
            <Category title="美食" :listDate="foods">
                <!--添加名称-->
                <template v-slot:center>
        			<img src="img1.jpg">
      			</template>
                <!--添加名称-->
    			<template v-slot:footer>
        			<a href="www.baidu.com">百度</a>
      			</template>
        	</Category>
            
        </div>
    </template>
    
    <script>
    	import Category from './components/Category'
        export default{
            name:'App',
            components:{Category}
        }
    </script>
    
  • 子组件:

    <template>
    	<div class="category">
            <!--指定名称-->
            <slot name="center"></slot>
            <!--指定名称-->
            <slot name="footer"></slot>
        </div>
    </template>
    <script>
        export default{
            name:'Category'
        }
    </script>
    
  • 解析:指定的代码会渲染到对应名称的slot上

3. 作用域插槽

当数据在组件的自身,而根据数据生成的结构需要组件的使用者来决定时,就要用作用域插槽

假设子组件<current-user>具有user对象数据,此时有如下代码

  • 父组件:

    <current-user>
      {{ user.firstName }}
    </current-user>
    
  • 子组件:

    <span>
      <slot></slot>
    </span>
    

以上代码不会正常工作,因为只有 <current-user> 组件可以访问到 user,而提供的内容是在父级渲染的

此时需要使用作用域插槽

  • 父组件:

    <current-user>
        <template v-slot:default="ScopeData">
    		{{ ScopeData.user.firstName }}
        </template>
    </current-user>
    
    
  • 子组件:

    <span>
      <slot :user="user"></slot>
    </span>
    
  • 解析:

    仔细看看和普通插槽相比,父子组件在使用作用域插槽时分别产生了哪些改变:

    • 父组件

      传统的v-slot:default后添加了="slotScope"

      而这个”slotScope”在插入内容中,用{{ ScopeData.user.firstName }}替代了 {{ user.firstName }}

    • 子组件

      子组件额外添加了一个:user="user"

    • 原理

      实际上在这里,父组件对子组件进行了一次传参,只不过传参与参数的接受仅仅局限于插槽之间

      绑定在 <slot> 元素上的 attribute 被称为插槽 prop,而在这个例子中,我们选择将包含所有插槽 prop 的对象命名为 slotProps

      也就是说,子组件用:user="user"user对象绑定在了slotProps上,然后传递了过去,父组件则用slotProps.user.firstName的方式接收到了。

      注意,这并不意味着作用域插槽可以用于子组件→父组件传递数据,实际逻辑为父组件→(需求子组件数据)→(发送请求)→(子组件绑定数据传输到父组件)→(父组件渲染)→(插入到子组件)→子组件。整体仍然是父组件传递数据到子组件

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30789.html

(0)
上一篇 2023-10-21 16:15
下一篇 2023-10-25 12:33

相关推荐

发表回复

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

关注微信