Skip to content

Vue3 插槽

前言

插槽的作用就是讲父组件里面的HTML内容传递给子组件

插槽类型

Vue3 插槽的使用方式非常灵活,允许你根据需求选择最合适的插槽类型

默认插槽

用于简单的内容传递

命名插槽

用于多个插槽,帮助你分配不同内容到不同的位置。

作用域插槽

允许子组件传递数据给父组件,以便父组件动态渲染插槽内容。

具名插槽组合

可以在一个组件中使用多个具名插槽,灵活分配父组件的内容。

基本插槽

基本插槽允许父组件传递内容到子组件中的指定位置。父组件内容会替换子组件中指定 <slot> 标签的位置

vue

<!-- Parent.vue -->
<template>
  <Child>
    <p>This is some content from the parent</p>
  </Child>
</template>
 
<script>
import Child from './Child.vue';
export default {
  components: { Child }
};
</script>
 
<!-- Child.vue -->
<template>
  <div>
    <slot></slot>  <!-- 插槽的位置 -->
  </div>
</template>

在这个例子中,父组件 Parent 向子组件 Child 传递了 <p> 标签内容,这些内容会替换子组件中的 <slot></slot> 部分。

命名插槽

如果你需要多个插槽,可以为每个插槽指定一个名称。父组件可以将内容插入到指定的命名插槽中。

vue
<!-- Parent.vue -->
<template>
  <Child>
    <template #header>
      <h1>Header Content</h1>
    </template>
    <template #footer>
      <p>Footer Content</p>
    </template>
  </Child>
</template>
 
<script>
import Child from './Child.vue';
export default {
  components: { Child }
};
</script>
 
<!-- Child.vue -->
<template>
  <div>
    <header>
      <slot name="header"></slot>  <!-- 命名插槽 -->
    </header>
    <footer>
      <slot name="footer"></slot>  <!-- 命名插槽 -->
    </footer>
  </div>
</template>

在这个例子中,父组件为 header 和 footer 插槽分别传递了内容。子组件通过 <slot name="header"><slot name="footer"> 分别插入不同的内容。

默认插槽内容

如果父组件没有传递内容给某个插槽,可以为插槽指定默认内容。

vue
<!-- Parent.vue -->
<template>
  <Child>
    <!-- 没有传递给插槽内容,使用默认插槽内容 -->
  </Child>
</template>
 
<script>
import Child from './Child.vue';
export default {
  components: { Child }
};
</script>
 
<!-- Child.vue -->
<template>
  <div>
    <slot>默认内容</slot>  <!-- 如果父组件没有传递内容,将使用默认内容 -->
  </div>
</template>

当父组件没有传递任何内容时,子组件中的 <slot> 会显示默认内容“默认内容”。

作用域插槽

有时你需要在插槽中传递一些数据给父组件,这时候就需要使用作用域插槽。作用域插槽允许子组件将数据传递给父组件,让父组件能动态渲染插槽内容。

vue
<!-- Parent.vue -->
<template>
  <Child v-slot:default="slotProps">
    <p>接收到的 message: {{ slotProps.message }}</p>
  </Child>
</template>
 
<script>
import Child from './Child.vue';
export default {
  components: { Child }
};
</script>
 
<!-- Child.vue -->
<template>
  <div>
    <slot :message="message"></slot>  <!-- 通过作用域插槽将数据传递给父组件 -->
  </div>
</template>
 
<script>
export default {
  data() {
    return {
      message: 'Hello from Child!'
    };
  }
};
</script>

在这个例子中,子组件通过 v-slot 绑定了一个作用域插槽,传递了一个 message 给父组件。父组件通过 slotProps 获取到这个数据并显示。

多插槽与具名插槽组合

你可以在一个组件中使用多个具名插槽,这允许父组件根据不同的插槽名称传递不同的内容。

vue

<!-- Parent.vue -->
<template>
  <Child>
    <template #header>
      <h1>This is the header</h1>
    </template>
    <template #main>
      <p>This is the main content</p>
    </template>
    <template #footer>
      <p>This is the footer</p>
    </template>
  </Child>
</template>
 
<script>
import Child from './Child.vue';
export default {
  components: { Child }
};
</script>
 
<!-- Child.vue -->
<template>
  <div>
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot name="main"></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>

这里,父组件为 header、main 和 footer 提供了不同的内容,子组件会根据插槽名称进行插入。

卡槽要给父元素传递值

  • Son.vue
vue
<template>
<div>
  <!--传递走两个值 一个是form 一个是model-->
  <slot name="action" :form="form" :model="model"></slot>
</div>  
</template>
<script setup lang="ts">
import {ref} from "vue"
const form = ref({name:'form'})
const model = ref({data:'model'})
</script>
  • Parent.vue
vue
<template>
  <Son>
    <template #action="{form,model}">
      <div>
        <p>{{form}}</p>
        <p>{{model}}</p>
      </div>
    </template>
  </Son>
</template>
<script setup lang="ts">
import Son from './Son.vue'
</script>