插槽配置
通过插槽在预设位置注入自定义内容
类型定义
interface SlotsConfig {
/**
* 标题栏插槽
*/
titleBar?: {
left?: ReactNode;
center?: ReactNode;
right?: ReactNode;
};
/**
* 侧边栏插槽
*/
sidebar?: {
header?: ReactNode;
footer?: ReactNode;
beforeNav?: ReactNode;
afterNav?: ReactNode;
};
/**
* Shell 插槽
*/
shell?: {
beforeContent?: ReactNode;
afterContent?: ReactNode;
};
}标题栏插槽
在标题栏的不同位置注入内容:
┌─────────────────────────────────────────────────┐
│ [left] [center] [right] [×] │
└─────────────────────────────────────────────────┘slots: {
titleBar: {
left: <SearchInput />,
center: <BreadcrumbNav />,
right: <UserMenu />,
},
},示例:添加搜索框
function SearchInput() {
return (
<input
type="search"
placeholder="搜索..."
className="h-7 w-48 rounded border px-2 text-sm"
/>
);
}
slots: {
titleBar: {
left: <SearchInput />,
},
},侧边栏插槽
在侧边栏的不同位置注入内容:
┌────────────┐
│ [header] │
├────────────┤
│[beforeNav] │
│ │
│ Nav Items │
│ │
│ [afterNav] │
├────────────┤
│ [footer] │
└────────────┘slots: {
sidebar: {
header: <WorkspaceSwitcher />,
beforeNav: <QuickActions />,
afterNav: <StorageIndicator />,
footer: <UserProfile />,
},
},示例:添加用户信息
function UserProfile() {
return (
<div className="flex items-center gap-2 p-3 border-t">
<img src="/avatar.png" className="w-8 h-8 rounded-full" />
<div>
<div className="text-sm font-medium">John Doe</div>
<div className="text-xs text-muted-foreground">john@example.com</div>
</div>
</div>
);
}
slots: {
sidebar: {
footer: <UserProfile />,
},
},示例:添加工作区切换器
function WorkspaceSwitcher() {
return (
<select className="w-full p-2 border-b text-sm">
<option>个人工作区</option>
<option>团队工作区</option>
</select>
);
}
slots: {
sidebar: {
header: <WorkspaceSwitcher />,
},
},Shell 插槽
在主内容区域前后注入内容:
┌────────────────────────────────────────┐
│ TitleBar │
├────────────┬───────────────────────────┤
│ │ [beforeContent] │
│ Sidebar ├───────────────────────────┤
│ │ Main Content │
│ ├───────────────────────────┤
│ │ [afterContent] │
└────────────┴───────────────────────────┘slots: {
shell: {
beforeContent: <AlertBanner />,
afterContent: <StatusBar />,
},
},示例:添加告警横幅
function AlertBanner() {
return (
<div className="bg-yellow-100 border-b border-yellow-200 px-4 py-2 text-sm text-yellow-800">
系统将于今晚 22:00 进行维护
</div>
);
}
slots: {
shell: {
beforeContent: <AlertBanner />,
},
},示例:添加状态栏
function StatusBar() {
return (
<div className="border-t px-4 py-1 text-xs text-muted-foreground flex justify-between">
<span>已连接</span>
<span>最后同步: 5 分钟前</span>
</div>
);
}
slots: {
shell: {
afterContent: <StatusBar />,
},
},完整示例
import { WorkspaceSwitcher } from './components/WorkspaceSwitcher';
import { UserProfile } from './components/UserProfile';
import { SearchInput } from './components/SearchInput';
import { StatusBar } from './components/StatusBar';
export const config = {
slots: {
titleBar: {
left: <SearchInput />,
},
sidebar: {
header: <WorkspaceSwitcher />,
footer: <UserProfile />,
},
shell: {
afterContent: <StatusBar />,
},
},
};注意事项
插槽内容是静态的,在配置时定义。如果需要动态内容,请在插槽组件内部处理状态。
// 正确:在组件内部管理状态
function DynamicCounter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}
slots: {
sidebar: {
footer: <DynamicCounter />,
},
},