slot又称插槽,通常用于父子组件之间,用于父组件向子组件传递模板内容

  • 在子组件中可以设定放置插槽的名称和要传递给父组件的子组件数据;
  • 在父组件中通过指令声明插槽和接收子组件传递的数据。

子组件中使用<slot>元素

在子组件中使用slot元素,当子组件渲染时,<slot>将会被替换为父组件的模板内容,slot元素相当于子组件留给父组件的占位符

子组件(Child)

<template>
	<h2>子组件</h2>
	<slot></slot>
</template>

父组件

<template>
	<h1>父组件</h1>
    <Child>
      <p>默认插槽的内容</p>
    </Child>
</template>
<script setup>
import Child from './Child.vue'
</script>

默认插槽和具名插槽

<slot> 组件可以使用 name属性来指定插槽名。如果不指定则默认为“default”,这样的插槽称为默认插槽,指定name属性则称为具名插槽

作用域插槽

在slot组件上绑定name以外的属性,可以把子组件的数据传递给父组件,这种插槽叫作用域插槽,实际上就是携带了子组件数据的插槽。

子组件(Child)

<template>
	<h2>子组件</h2>
	<slot name="header"></slot>
	<slot></slot>
	<slot name="footer" msg="子组件的数据"></slot>
</template>

父组件中使用v-slot指令

在父组件中用于声明具名插槽或是期望接收子组件属性的作用域插槽,如果没有使用v-slot指令,模板内容将替换默认插槽。
PS:
vue3中规定v-slot只能添加在<template>标签上
v-slot指令可以简写,将v-slot:替换为字符 #

  • 父组件
<template>
    <h1>父组件</h1>
    <Child>
      <template v-slot:header>Header</template>
      <p>默认插槽的内容</p>
      <template #footer="{ msg }">{{ msg }}</template>
    </Child>
</template>
<script setup lang="ts">
import Child from './Child.vue'
</script>

在子组件中获取父组件传入的插槽对象

  • 可以在子组件模板中直接通过 $slots获取父组件传入的插槽对象
  • 组合式api中通过context.slots,获取父组件传入的插槽对象
  • <script setup>语法糖中可以使用useSlots()辅助函数,获取父组件传入的插槽对象
<script>
export default {
  setup(props, context) {
    console.log(context.slots)
  }
}
</script>
<script setup>
import { useSlots } from 'vue'
const slots = useSlots()
</script>

在这里插入图片描述

插槽透传

插槽可以向子组件传递模板,但有时候我们希望跨越多层级传递模板,如二次封装element的组件,需要支持原属性和插槽。通过在子组件中获取父组件传入的插槽对象,就可以实现插槽透传。

  • 父组件

    <template>
       <h1>父组件</h1>
       <Child>
         <template v-slot:header>Header</template>
         <p>默认插槽的内容</p>
         <template #footer="{ msg }">{{ msg }}</template>
       </Child>
    </template>
    <script setup lang="ts">
    import Child from './Child.vue'
    </script>
    
  • 孙组件

    <template>
       <h3>孙组件</h3>
       <slot name="header"></slot>
       <slot></slot>
       <slot name="footer" msg="孙组件的数据"></slot>
    </template>
    
  • 子组件

    <template>
       <h2>子组件</h2>
       <Son>
         <template v-for="name in Object.keys($slots)" :key="name" #[name]="scope">
           <slot :name="name" v-bind="scope" />
         </template>
       </Son>
    </template>
    <script setup lang="ts">
    import Son from './Son.vue'
    </script>
    

    其中
    在这里插入图片描述
    相当于

    	<template #header="scope">
          <slot name="header" v-bind="scope" />
        </template>
        <template #footer="scope">
          <slot name="footer" v-bind="scope" />
        </template>
        <template #default="scope">
          <slot name="default" v-bind="scope" />
        </template>
    
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐