Vue3插槽

前言:

        Vue3 的插槽(Slots)是组件化开发中的重要特性,它允许开发者灵活地组合和分发内容,实现更高效的组件复用和定制。插槽机制为父子组件之间的内容传递提供了强大的支持,无论是默认插槽、具名插槽还是作用域插槽,都能满足多样化的开发需求。

        随着 Vue3 的推出,插槽功能得到了进一步优化,性能更高效,逻辑更清晰。本文将从基础概念出发,逐步解析 Vue3 插槽的使用方式、常见场景以及高级技巧,帮助开发者更好地理解和运用这一核心功能。无论是构建动态布局、设计可复用的 UI 组件,还是实现复杂的交互逻辑,插槽都能成为开发中的得力工具。

1.默认插槽

        默认插槽是 Vue3 中最基础的插槽类型,用于接收父组件传递的匿名内容。当子组件未定义具名插槽时,所有内容都会渲染到默认插槽的位置。

子组件定义:

        在子组件中,使用<slot>标签作为占位符,标记父组件内容插入的位置。若父组件未提供内容,可设置默认内容作。

<!-- ChildComponent.vue -->
<template>
    <div>
        <header>
            <slot>默认内容(当父组件未传递时显示)</slot>
        </header>
        <main>
            <slot></slot>
        </main>
        <footer>
            <slot></slot>
        </footer>
    </div>
</template>

父组件使用:

<template>
  <div class="app">
    <ChildComponent>
      <p>这是父组件传递给默认插槽的内容</p>
    </ChildComponent>
  </div>
</template>

<script setup>
import ChildComponent from './components/ChildComponent.vue';
</script>

标准写法:

<template>
  <div class="app">
    <ChildComponent>
      <!-- 默认插槽 -->
      <template #default>
        <p>这是父组件传递给默认插槽的内容</p>
      </template>
    </ChildComponent>
  </div>
</template>

        #号表示v-slot的缩写,default表示默认插槽。

        打开页面可以看到所有slot标签中的内容全部被父组件中的内容插入替代了,当我们想要分类来插入时就用到了具名插槽。

2.具名插槽

        其实就是给子组件中的slot标签其一个名字,然后在父组件中根据其的名称,将内容插入到对的插槽中。

子组件定义:

<!-- ChildComponent.vue -->
<template>
    <div>
        <header>
            <slot>默认内容(当父组件未传递时显示)</slot>
        </header>
        <main>
            <slot name="main"></slot>
        </main>
        <footer>
            <slot name="footer"></slot>
        </footer>
    </div>
</template>

 父组件使用:

<template>
  <div class="app">
    <ChildComponent>
      <!-- 默认插槽 -->
      <template #default>
        <p>这是父组件传递给默认插槽的内容</p>
      </template>

      <!-- 具名插槽 -->
       <template #main>
        <p>这是给main插入的内容</p>
       </template>
       <template #footer>
        <p>这是给footer插入的内容</p>
       </template>
    </ChildComponent>
  </div>
</template>

<script setup>
import ChildComponent from './components/ChildComponent.vue';
</script>

页面效果:

注意事项:

  • 组件中最多只能存在一个默认插槽
  • 未命名的<slot>自动成为默认插槽
  • 名插槽内容必须用<template>包裹
  • 插槽名称需保持唯一性

3.动态插槽

        动态插槽允许在父组件中通过变量动态指定插槽名称,实现更灵活的组件内容分发。这种模式适用于需要根据运行时条件切换不同插槽内容的场景。

子组件定义:

<!-- ChildComponent.vue -->
<template>
    <div>
        <header>
            <slot name="header">默认内容(当父组件未传递时显示)</slot>
        </header>
        <main>
            <slot name="main"></slot>
        </main>
        <footer>
            <slot name="footer"></slot>
        </footer>
    </div>
</template>

        子组件需预定义多个具名插槽,供父组件动态选择。

父组件动态绑定:

<template>
  <div class="app">
    <ChildComponent>
      <template #[dynamicSlotName]>
        <p>这是父组件传递给{{ dynamicSlotName }}的内容</p>
      </template>
      <template #main>
        <p>这是给main插入的内容</p>
      </template>
      <template #footer>
        <p>这是给footer插入的内容</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './components/ChildComponent.vue';

const dynamicSlotName = ref('header')
</script>

        当需要批量控制多个动态插槽时,可以使用v-for循环。代码如下:

<template>
  <div class="app">
    <ChildComponent>
      <template v-for="(value, name) in slotMap" :key="name" #[name]>
        <p>这是给{{ name }}插入的内容</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './components/ChildComponent.vue';

const slotMap = ref({
  header: '头部内容',
  main: '主体内容',
  footer: '尾部内容'
})

</script>

4.作用域插槽

        作用域插槽是Vue.js中一种特殊的插槽机制,允许子组件将数据传递到父组件中定义的插槽内容。与普通插槽不同,作用域插槽可以访问子组件内部的数据,从而实现更灵活的模板定制。

作用域插槽的基本语法:

        在子组件中,通过slot标签绑定需要传递的数据,以默认插槽为例:

子组件:

<!-- ChildComponent.vue -->
<template>
    <div>
        <header>
            <slot :data="childData"></slot>
        </header>
    </div>
</template>

<script setup>
import { ref } from 'vue';

const childData = ref('我是ChildComponent.vue中的内容')
</script>

父组件:

<template>
  <div class="app">
    <ChildComponent>
      <template #default="slotProps">
        <p>{{ slotProps.data  }}</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script setup>
import ChildComponent from './components/ChildComponent.vue';
</script>

 或者使用解构赋值的方式:

<template>
  <div class="app">
    <ChildComponent>
      <template #default="{ data }">
        <p>{{ data }}</p>
      </template>
    </ChildComponent>
  </div>
</template>

<script setup>
import ChildComponent from './components/ChildComponent.vue';
</script>

        具名插槽同理。

总结:

        Vue3 的插槽机制为组件化开发提供了强大的内容分发能力,通过不同类型的插槽可以实现灵活的组件组合和复用。

默认插槽

  • 子组件使用 <slot> 作为内容占位符
  • 父组件内容自动填充到未命名的插槽位置
  • 可通过 <template #default> 显式指定默认插槽内容

具名插槽

  • 子组件中为 <slot> 添加 name 属性命名
  • 父组件通过 <template #slotName> 定向分发内容
  • 多个插槽需保持名称唯一性

动态插槽

  • 使用变量动态绑定插槽名称 #[dynamicName]
  • 适合需要运行时切换插槽内容的场景
  • 可通过 v-for 批量处理多个动态插槽

作用域插槽

  • 子组件通过 <slot :data="value"> 传递数据
  • 父组件接收插槽 props 进行定制化渲染
  • 支持解构赋值简化模板代码

        插槽的合理运用可以显著提升组件的复用性和灵活性,是构建高质量 Vue 应用的重要技术手段。

### Vue3插槽的使用教程 #### 默认插槽 (Default Slot) 在 Vue3 中,默认插槽是最简单的形式,它允许父组件向子组件传递内容而无需指定特定的名字。如果一个子组件只包含一对 `<slot></slot>` 标签,则该位置会被默认插槽填充。 ```html <!-- 子组件 ChildComponent.vue --> <template> <div class="child"> <h1>这是子组件的内容</h1> <!-- 默认插槽 --> <slot></slot> </div> </template> <script> export default { name: &#39;ChildComponent&#39; } </script> ``` 父组件可以通过如下方式传入内容: ```html <!-- 父组件 ParentComponent.vue --> <template> <div class="parent"> <h1>这是父组件的内容</h1> <ChildComponent> 我是通过默认插槽插入到子组件中的内容。 </ChildComponent> </div> </template> <script> import ChildComponent from &#39;./ChildComponent.vue&#39;; export default { components: { ChildComponent } }; </script> ``` 此代码展示了如何利用默认插槽将数据从父组件传递给子组件[^1]。 --- #### 具名插槽 (Named Slots) 当需要在一个子组件中定义多个不同的插槽时,可以使用具名插槽Vue3 要求使用 `v-slot` 指令并配合模板标签 `<template>` 来声明具名插槽。 ```html <!-- 子组件 NamedSlotsExample.vue --> <template> <div class="named-slots-example"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer">默认 footer 内容</slot> </footer> </div> </template> <script> export default { name: &#39;NamedSlotsExample&#39; }; </script> ``` 父组件则需按照以下方式进行绑定: ```html <!-- 父组件 UsingNamedSlots.vue --> <template> <div class="using-named-slots"> <NamedSlotsExample> <template v-slot:header> <h1>这里是头部区域</h1> </template> <p>这是主体部分。</p> <template v-slot:footer> 这里是底部区域 </template> </NamedSlotsExample> </div> </template> <script> import NamedSlotsExample from &#39;./NamedSlotsExample.vue&#39;; export default { components: { NamedSlotsExample } }; </script> ``` 上述例子说明了如何创建和使用具名插槽,并且演示了动态替换默认内容的功能。 --- #### 动态插槽名 (Dynamic Slot Names) 有时插槽名字可能并非固定不变,而是由变量决定。在这种情况下,可以用方括号包裹表达式作为属性值的方式设置动态插槽名。 ```html <!-- 子组件 DynamicSlotName.vue --> <template> <div class="dynamic-slot-name"> <slot :name="dynamicSlotName"></slot> </div> </template> <script> export default { data() { return { dynamicSlotName: &#39;example&#39; // 可以是一个计算属性或者响应式的 prop 值 }; }, name: &#39;DynamicSlotName&#39; }; </script> ``` 对应的父组件写法如下所示: ```html <!-- 父组件 UseDynamicSlotName.vue --> <template> <div class="use-dynamic-slot-name"> <DynamicSlotName> <template #[dynamicSlotName]> <span>我是被动态命名的插槽内容</span> </template> </DynamicSlotName> </div> </template> <script> import DynamicSlotName from &#39;./DynamicSlotName.vue&#39;; export default { components: { DynamicSlotName }, computed: { dynamicSlotName() { return this.$store.state.currentSlot || &#39;default&#39;; // 示例逻辑 } } }; </script> ``` 这里展示了一个场景,在其中插槽名称是由外部状态驱动变化的情况。 --- #### 插槽作用域 (Scoped Slots) 作用域插槽允许子组件将其内部的数据暴露出来供父组件消费。这通常用于列表渲染或其他复杂交互场合下共享局部上下文信息。 ```html <!-- 子组件 ScopedSlotDemo.vue --> <template> <ul> <li v-for="(item, index) in items" :key="index"> <slot :text="item.text">{{ item.text }}</slot> </li> </ul> </template> <script> export default { data() { return { items: [ { text: &#39;苹果&#39; }, { text: &#39;香蕉&#39; }, { text: &#39;橙子&#39; } ] }; }, name: &#39;ScopedSlotDemo&#39; }; </script> ``` 父组件可以根据需求自定义显示样式: ```html <!-- 父组件 ConsumeScopedSlot.vue --> <template> <div class="consume-scoped-slot"> <ScopedSlotDemo> <template #default="{ text }"> {{ `${text} 是一种水果.` }} </template> </ScopedSlotDemo> </div> </template> <script> import ScopedSlotDemo from &#39;./ScopedSlotDemo.vue&#39;; export default { components: { ScopedSlotDemo } }; </script> ``` 这段代码片段解释了如何借助作用域插槽让父子组件之间更灵活地协作处理数据流[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值