Vue里的slot

930 阅读3分钟

以下内容适用于vue 2.6.0及以后的版本

插槽作用

Vue 实现了一套内容分发的 API,这套 API 的设计灵感源自 Web Components 规范草案,将 slot 元素作为承载分发内容的出口。

插槽分类

Vue里的插槽大概可以分为三类,分别是匿名插槽,具名插槽以及作用域插槽。

插槽介绍

子组件

<div>
    <p>
      <slot name="header">我是header后备内容</slot>
    </p>
    <p>
      <slot>我是content后备内容</slot>
    </p>
    <p>
      <slot name="footer">我是footer后备内容</slot>
    </p>
</div>

父组件

<template v-slot:header>header</template>
<template v-slot:default>content</template>
<template v-slot:footer>footer</template>

如上所示,在vue2.6版本后,具名插槽的使用方式是:首先在子组件中给slot添加name属性,然后在父组件的template中利用v-slot指令并制定name值,就会将父组件中该template的内容渲染到子组件对应的slot中。

渲染结果

注1

  • 同其它指令一样,v-slot指令也有自己的语法糖,可以将v-slot替换为#,但#后必须指定name属性值,如果是匿名插槽,则为#default。
  • 内容分发的时候最好使用template包裹起来,如果子组件中有匿名插槽,并且父组件中未指定匿名插槽的内容,则默认将所有内容添加到匿名插槽下。
  • 后备内容指的是在父组件中未指定插槽内容时,子组件显示的内容。

作用域插槽

有时让插槽内容能够访问子组件中才有的数据是很有用的,作用域插槽可以向父组件传递子组件中的插槽数据,从而父组件可以根据插槽中的数据对插槽的内容进行修改。

子组件

<p>
     <slot :test="msg">我是content后备内容</slot>
</p>
data() {
    return {
      msg: '我是插槽想要传递回来的信息'
    }
}

父组件

<template #default='slotProps'>
       <h3>{{ slotProps.test }}</h3>
       <ul>
         <li v-for='i in 5' :key='i'>这是第{{ i }}条新闻</li>
       </ul>
</template>

渲染结果

作用域插槽的使用方式:首先在子组件的插槽上自定义属性并传递参数,该属性被添加到插槽props对象中,然后在父组件的slotProps中获取该属性。

注2

  • 自定义属性可以随意书写,只不过在获取属性时要相互对应;slotProps也可以修改,但为了语义化以及书写习惯,最好不要修改。
  • 因为v-slot:default=提供了一个js环境,可以利用解构赋值来更方便的获取该属性值,以及修改属性名和设置默认值。 如父组件:
 <template #default='{ test: childMsg }'>
        <h3>{{ childMsg }}</h3>
        <ul>
          <li v-for='i in 5' :key='i'>这是第{{ i }}条新闻</li>
        </ul>
 </template>

实际场景&原理

有待补充