Skip to content

插槽

插槽让父组件把内容传给子组件。ElfUI 输出 Custom Element,默认插槽和具名插槽使用原生 Web Components 语义。

默认插槽

ts
export const Card = defineHtml(`
  <article class="card">
    <slot></slot>
  </article>
`);
html
<elf-card>内容</elf-card>

具名插槽

ts
export const Panel = defineHtml(`
  <header><slot name="title"></slot></header>
  <main><slot></slot></main>
  <footer><slot name="actions"></slot></footer>
`);
html
<elf-panel>
  <h2 slot="title">标题</h2>
  正文
  <button slot="actions">确定</button>
</elf-panel>

作用域插槽

Web Components 没有原生作用域 slot。ElfUI 通过编译期桥接支持常用写法,子组件使用 useScopedSlot() 消费。

ts
import { defineHtml, useScopedSlot } from "@elfui/core";

const itemSlot = useScopedSlot<{ item: string }>("item");

export const ListBox = defineHtml(`
  <ul>
    <li>${itemSlot?.({ item: "A" })}</li>
  </ul>
`);

父组件用带作用域参数的 <template #name="..."> 提供渲染函数:

ts
export const UserListPage = defineHtml(`
  <user-list>
    <template #item="{ item, index }">
      <strong>{{ index + 1 }}</strong>
      <span>{{ item.name }}</span>
    </template>
  </user-list>
`);

itemindex 是 slot 局部变量,因此这里使用模板表达式,而不是外层 TypeScript 的 ${...}。子组件的 useScopedSlot<{ item: User; index: number }>("item") 泛型同时约束它传出的 scope。

作用域插槽适合 Table cell、List item 这类需要把子组件内部数据交给父组件渲染的场景。