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

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

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

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

  1. 默认插槽
    父组件:

    子组件:

    解析:

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

若Category中定义了插槽,则这段代码会被替换为;若没有,则父组件传入的代码会被自动抛弃

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

注意:

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

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

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

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

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

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

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

父组件:

<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>

子组件:

解析:指定的代码会渲染到对应名称的slot上

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

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

父组件:

<current-user>
  {{ user.firstName }}
</current-user>

子组件:

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

以上代码不会正常工作,因为只有 组件可以访问到 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"

原理

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

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

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

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

插槽

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

标签: none

添加新评论