插槽 Slots

来源: 2024-05-26 06:56:57 播报

插槽内容与出口

父组件为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。

示例:

<FancyButton>
  Click me! <!-- 插槽内容 -->
</FancyButton>
<!-- <FancyButton> -->
<button class="fancy-btn">
  <slot></slot> <!-- 插槽出口 -->
</button>

结果:

<button class="fancy-btn">Click me!</button>

slot 元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。

插槽内容可以是任意合法的模板内容,除了文本。还可以是多个元素,甚至是组件。

渲染作用域

插槽内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件模板中定义的。但它无法访问子组件的数据。

默认插槽

子组件仅有一个没有带任何属性的slot标签。

示例:

<button type="submit">
  <slot></slot>
</button>

默认内容是指写在 slot 标签之间的内容,当,父组件没有提供内容时,就展示默认内容。

示例:

<button type="submit">
  <slot>
    Submit <!-- 默认内容 -->
  </slot>
</button>

具名插槽

slot 元素通过name属性,来给各个插槽分配唯一的 ID。

示例:

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

向具名插槽传入内容,使用含 v-slot 指令的 template 元素,将目标插槽的名字传给该指令。

示例:

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

v-slot 的简写 #,所以 template v-slot:header 可以简写为 template #header。

条件插槽

根据插槽是否存在来渲染某些内容。使用 $slots 属性与 v-if 来实现。

示例:

<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>

动态插槽名

示例:

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

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

作用域插槽

插槽的内容使用子组件域内的数据。我们需要向一个插槽的出口上传递 attributes。

子组件传入插槽的 props 作为了 v-slot 指令的值,可以在插槽内的表达式中访问。

示例:

<!-- <MyComponent> 的模板 -->
<div>
  <slot :text="greetingMessage" :count="1"></slot>
</div>

默认作用域插槽

默认插槽接受到插槽 props 对象:v-slot="slotProps"。

示例:

<MyComponent v-slot="slotProps">
  {{ slotProps.text }} {{ slotProps.count }}
</MyComponent>

具名作用域插槽

具名插槽接受到插槽 props 对象:v-slot:name="slotProps"。

示例:

<MyComponent>
  <template v-slot:header="headerProps">
    {{ headerProps }}
  </template>

  <template v-slot:default="defaultProps">
    {{ defaultProps }}
  </template>

  <template v-slot:footer="footerProps">
    {{ footerProps }}
  </template>
</MyComponent>

缩写:

<MyComponent>
  <template #header="headerProps">
    {{ headerProps }}
  </template>

  <template #default="defaultProps">
    {{ defaultProps }}
  </template>

  <template #footer="footerProps">
    {{ footerProps }}
  </template>
</MyComponent>