Vue3系列(九)Composition Api之动态组件及插槽的使用

918 阅读1分钟

动态组件

通过<component>标签,让多个组件实现动态切换

要渲染的实际组件通过 is属性传递决定

  • 当 is 是字符串,它既可以是 HTML 标签名也可以是组件的注册名(想通过名称传递则必须先对其进行注册)。

    <template>
      <component :is="isGroup ? 'TransitionGroup' : 'Transition'"> ... </component>               </template>
    
    <script>
    import { Transition, TransitionGroup } from 'vue'
    
    export default {
      components: {
        Transition,
        TransitionGroup
      }
    }
    </script> 
    
  • 或者is 也可以直接绑定到组件的定义。

    <template>
       <component :is="Math.random() > 0.5 ? Foo : Bar" />
    </template>
    
    <script setup>
    import Foo from './Foo.vue'
    import Bar from './Bar.vue'
    </script>
    

插槽

插槽就是组件使用<slot><、slot>留出一个对应的位置,这个位置的内容由父组件提供

匿名插槽

子组件内放置一个插槽,用于接收父组件传递的内容

// chlidren.vue
<template>
  <div>
    我是子组件
    
    <slot></slot>
  </div>
</template>

父组件引入子组件,并给插槽填充内容,v-slot 有对应的简写 #,可以简写为<template #default>

// parent.vue
<template>
  <div>
    <Children>
      <template v-slot>
        <div>我是父组件填充的内容</div>
      </template>
    </Children>
  </div>
</template>

具名插槽

具名插槽允许我们给插槽取个自定义名字

由于一个子组件可以放多个插槽,而且可以放在不同的地方,而父组件填充内容时,可以根据这个名字把内容填充到对应插槽中

// Layout.vue
<div class="container">
  <header>
    <!-- 标题内容放这里 -->
    <slot name="header"></slot>
  </header>
  <main>
    <!-- 主要内容放这里 -->
    <slot name="header"></slot>
  </main>
  <footer>
    <!-- 底部内容放这里 -->
    <slot name="header"></slot>
  </footer>
</div>

页面使用,通过v-slot指定对应的插槽名称,v-slot 有对应的简写 #,可以简写为<template #header>

// 使用
<BaseLayout>
  <template v-slot:header>
  <!-- header 插槽的内容放这里 -->
  </template
</BaseLayout>

作用域插槽

在某些场景下插槽的内容可能想要同时使用父组件域内和子组件域内的数据,也就是可以在子组件的<slot>标签中,通过参数绑定,派发给父组件去使用

// chlidren.vue
<template>
  <div v-for="item in 100">
    <slot :data="item"></slot>
  </div>
</template>

引用页面通过解构方式获取值

// parent.vue
<template>
  <div>
    <Children>
      <template #default="{data}">
        <div>{{ data }}</div>
      </template>
    </Children>
  </div>
</template>

动态插槽名

动态参数在 v-slot 上也是有效的,即可以定义下面这样的动态插槽名:

<base-layout>
  <template v-slot:[name]>
    ...
  </template>

  <!-- 缩写为 -->
  <template #[name]> 
    ...
  </template>
</base-layout>

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

const name = ref('header')
<script>