vue3中slot(插槽)的详细使用

在 Vue 3 中,slot(插槽)是一种强大的组件内容分发机制,它允许父组件向子组件传递内容,从而使组件的使用更加灵活。以下是关于 Vue 3 中 slot 的详细介绍

一、默认插槽

  • 这是最基本的插槽形式。子组件中使用定义一个插槽,父组件可以将内容放置在子组件标签对之间来填充这个插槽。
    子组件代码示例 childTest.vue

    复制代码
    <template>
      <div class="child_wrap">
       <slot></slot>
      </div>
    </template>

    父组件代码示例parentTest.vue

    复制代码
    <template>
      <childTest>1111</childTest>
    </template>
    <script setup lang="ts">
     import childTest from './childTest.vue';    
    </script>

    父组件中的

    标签内容就会被插入到子组件的默认插槽位置,即子组件
    内的位置

二、具名插槽

  • 当子组件需要定义多个插槽时,就可以使用具名插槽来区分这些插槽。
  • 在子组件中,给标签添加name属性来指定插槽的名称。父组件则通过v-slot:slotName或者简写#slotName来指定内容应该放置到哪个具名插槽

子组件代码示例 childTest.vue

复制代码
<template>
    <div class="child_wrap">
     <slot></slot>
     <slot name="header"></slot>
     <slot name="content"></slot>
     <slot name="footer"></slot>
    </div>
</template>

父组件代码 parentTest.vue

复制代码
<template>
    <childTest>
        <p>1111</p>
        <template v-slot:header>
            <h3>This is the header</h3>
        </template>
        
        <template #content>
            <p>This is the content section</p>
        </template>

        <template v-slot:footer>
            <p>This is the footer</p>
        </template>
    </childTest>
</template>

父组件通过v-slot:header、#content(简写形式)和v-slot:footer将不同的内容分别放入子组件的header、content和footer具名插槽中

三、作用域插槽

  • 作用域插槽允许子组件向父组件传递数据,父组件可以基于这些数据来渲染内容。
  • 在子组件中,通过在标签上使用v-bind(或简写:)将数据传递给插槽。父组件在使用作用域插槽时,可以通过模板内的slotProps对象来访问子组件传递的数据。

子组件代码

复制代码
<template>
    <div class="child_wrap">
     <!-- <slot></slot>
     <slot name="header"></slot>
     <slot name="content"></slot>
     <slot name="footer"></slot> -->
     <slot name="item" :item="itemData"></slot>
    </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
const itemData = ref({
    name: 'John',
    age: 30,
})
</script>

父组件

复制代码
<template>
    <childTest>
        <!-- <p>1111</p> -->
        <!-- <template v-slot:header>
            <h3>This is the header</h3>
        </template>

        <template #content>
            <p>This is the content section</p>
        </template>

        <template v-slot:footer>
            <p>This is the footer</p>
        </template> -->
        <template v-slot:item="slotProps">
        <div>
          <p>Age: {{ slotProps.item.age }}</p>
          <p>Name: {{ slotProps.item.name }}</p>
        </div>
      </template>
    </childTest>
</template>

子组件通过将itemData数据传递给名为item的作用域插槽。父组件通过v-slot:item="slotProps"接收这个数据,并在模板中使用slotProps.item来访问和渲染这些数据

四、动态插槽

  • 动态插槽允许你根据条件动态地选择要渲染的插槽。这可以通过 v-bind 动态绑定插槽名来实现
    子组件 childTest.vue

父组件 childTest.vue

复制代码
<template>
   <childTest>
       1111
       <template v-slot:[dynamicSlotName]>
       <p>这是动态插槽的内容</p>
     </template>
   </childTest>
</template>

<script setup lang="ts">
import childTest from './childTest.vue';
import { ref } from 'vue';
const dynamicSlotName = ref('dynamicSlot');

</script>

<style scoped></style>

父组件通过v-slot:dynamicSlotName、#dynamicSlotName(简写形式)

五、条件插槽

  • 使用 $slots 属性与 v-if 来实现。

  • 我们定义了一个卡片组件,它拥有三个条件插槽:header、footer 和 default。 当 header、footer 或 default 的内容存在时,我们希望包装它以提供额外的样式
    父组件 parentTest.vue

子组件 childTest.vue

复制代码
 <div class="card">
  <div v-if="$slots.header" class="card-header">
    <slot name="header" />
  </div>
  
  <div v-if="$slots.default" class="card-content">
    <slot />
  </div>
  
  <div v-if="$slots.footer" class="card-footer">
    <slot name="footer" />
  </div>
</div>
</template>
在 Vue 3 中,你可以使用 v-slots 指令来以对象的形式定义插槽内容。这种方式允许你在模板中以更灵活的方式定义多个插槽。以下是一个示例,展示如何使用 v-slots 来定义默认插槽和其他插槽的内容。

父组件代码

复制代码
<template>
  <div>
    <childTest
      v-slots="{
        default: () => <p>这是默认插槽的内容</p>,
        header: () => <h3>这是标题插槽的内容</h3>,
        footer: () => <button @click="handleClick">这是页脚插槽的内容</button>
      }"
    />
  </div>
</template>

<script setup lang="ts">
import childTest from './childTest.vue';

const handleClick = () => {
  console.log('按钮被点击了');
};
</script>

<style scoped></style>

子组件代码(childTest.vue)

复制代码
<template>
  <div class="card">
    <div v-if="$slots.header" class="card-header">
      <slot name="header" />
    </div>
    
    <div v-if="$slots.default" class="card-content">
      <slot />
    </div>
    
    <div v-if="$slots.footer" class="card-footer">
      <slot name="footer" />
    </div>
  </div>
</template>

<style scoped>
.card {
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  overflow: hidden;
  margin: 20px 0;
}

.card-header {
  background-color: #f5f5f5;
  padding: 16px;
  border-bottom: 1px solid #e0e0e0;
}

.card-content {
  padding: 16px;
}

.card-footer {
  background-color: #f5f5f5;
  padding: 12px 16px;
  border-top: 1px solid #e0e0e0;
  text-align: right;
}
</style>
相关推荐
狂师10 分钟前
比 Playwright 更给力,推荐一个AI Agent的浏览器自动化开源项目!
前端·开源·测试
IT_陈寒19 分钟前
React hooks 闭包陷阱把我的状态吃掉了,原来问题出在这里
前端·人工智能·后端
壹方秘境21 分钟前
使用ApiCatcher在 iOS 上像修改 hosts 一样自定义域名解析
前端·后端·客户端
柳杉43 分钟前
可视化大屏设计器脚手架:从设计到交付的一站式方案
前端·three.js·数据可视化
铁皮饭盒1 小时前
3行代码搞定页面截图,Bun.WebView真的简单
javascript
kyriewen14 小时前
我手写了一个 EventEmitter,面试官追问了 6 个问题——第 4 个我没答上来
前端·javascript·面试
IT_陈寒14 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
山河木马15 小时前
矩阵专题2-怎么创建视图矩阵(uViewMatrix)
javascript·webgl·计算机图形学
小林攻城狮15 小时前
使用 Transport 节流解决 Vercel AI SDK 流式渲染卡死问题
前端·react.js
前端缘梦15 小时前
告别 TS 运行时类型漏洞!Zod 完整入门实战教程(前端 / 全栈必备)
前端·react.js·全栈