vue的几种插槽

169 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情

前言

组件之间有父子组件之说,在于可以使用props进行数据的传递。但是在某些特定的业务场景下需要将模版内容直接给子组件,而子组件只起到渲染的作用,比如dialog组件,头部固定为标题,底部固定为按钮,中间内容自定义(可能是表单、表格、列表等)且要适用于整个业务,那么使用props的话子组件的模版内容会很长,可能会是这样:

<script setup>
  
</script>
<template>

   <div v-if="表格">
     ......
   </div>
   <div v-else-if="表单">
     ......
   </div>
   <div v-else-if="列表">
     ......
   </div>
</template>
<style lang="scss" scoped>

</style>


,但是使用插槽的话情况会得到改观,中间自定义内容让父组件去控制传递给子组件的是什么的模版内容。

插槽

<slot>是元素的出口,标记了父组件的内容需要在子组件的哪里被渲染。 而它又分为三种:

  • 默认插槽
  • 具名插槽
  • 作用域插槽

默认插槽

默认插槽是直接使用<slot />,在外部提供的模版内容没有指定在哪块区域渲染的会默认渲染在此处。

//子组件

<template>
    
   <slot> </slot>
</template>

//父组件
//提供了插槽内容
<template>
  <dialog-vue>
     默认内容 
  </dialog-vue>
</template>

//没有提供插槽内容
<template>
  <dialog-vue>
  </dialog-vue>
</template>

a.png

同时可以自定的默认的内容,就是在父组件里面没有提供任何插槽内容时,会渲染默认的内容。

b.png

具名插槽

顾名思义就是有名字的插槽,这个在一个组件中提供了多个出口时很实用。

// 子组件
<template>
  <slot name="top"></slot>
   <slot> 这是没有提供任何插槽内容</slot>
   <slot  name="bottom"></slot>
</template>
//父组件
<script setup>

import dialogVue from './dialog/index.vue'
</script>

<template>
  <dialog-vue>
     <!-- 默认内容  -->
     <!-- v-slot:top可以简写成#top  -->
    <template #top>
      <h1>头部标题</h1>
    </template>
     自定义内容
     <template #bottom>
       这是底部的内容
     </template>
  </dialog-vue>
</template>


c.png

插槽名可以在data中进行定义,让其可以改变。

作用域插槽

某些场景下需要访问到子组件中的状态就可以使用作用域插槽。

// 子组件

<template>
  <slot name="top"></slot>
   <slot> 这是没有提供任何插槽内容</slot>
   <slot  name="bottom"></slot>

   <!-- 作用域插槽 -->
   <slot text="作用域插槽"> </slot>
</template>

// 父组件
<template>
  <dialog-vue v-slot="{ text }">
    {{ text }}
  </dialog-vue>
</template>

d.png

也可以和具名插槽那样给的名字,渲染在对应的位置。

//子组件
<template>
  <slot name="top"></slot>
   <slot> 这是没有提供任何插槽内容</slot>
   <slot  name="bottom"></slot>

   <!-- 作用域插槽 -->
   <slot name="header" text="作用域插槽"> </slot>
</template>

// 父组件
<template>
  <dialog-vue >
     <template #header="headerprop">
       <h1>
        {{ headerprop}}
       </h1> 
     </template>
  </dialog-vue>
</template>

e.png