插槽
插槽让父组件把内容传给子组件。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>
`);item 和 index 是 slot 局部变量,因此这里使用模板表达式,而不是外层 TypeScript 的 ${...}。子组件的 useScopedSlot<{ item: User; index: number }>("item") 泛型同时约束它传出的 scope。
作用域插槽适合 Table cell、List item 这类需要把子组件内部数据交给父组件渲染的场景。
