插槽报“Undefined variable”是因为命名插槽变量(如$header)仅在父组件传入对应<x-slot name="header">时才被注入,未传则变量不存在;应使用{{ $header ?? '默认值' }}或@isset($header)安全访问。

插槽不是“自动继承变量的魔法入口”,而是显式内容搬运工;用错就报 Undefined variable 或渲染空白,根本原因在于你没判断变量是否存在、没区分 $slot 是字符串还是闭包、也没搞清命名插槽和默认插槽的注入逻辑。
为什么 $header 渲染时报 “Undefined variable”?
Blade 不会为你初始化命名插槽变量——$header、$footer 这些变量只在你用了对应 <x-slot name="header"></x-slot> 时才被注入。没传,它就真不存在。
- 错误写法:
{{ $header }}→ 直接抛异常 - 安全写法:
{{ $header ?? '默认标题' }}或更推荐@isset($header){{ $header }}@endisset - 调试技巧:在组件开头加
{{ dump(get_defined_vars()) }},一眼看清哪些插槽变量实际被注入了 - 别混用
@props(['title'])和$header——前者是属性机制,后者是插槽机制,底层不互通
$slot 有时是字符串,有时是 Closure,怎么判断和调用?
类型取决于你传进去的内容:纯 HTML → 字符串;含 @foreach 或 {{ $user->name }} → Closure;用了 scope: true → 也是 Closure,但执行上下文不同。
- 静态内容:
{{ $slot }}就够了 - 带 Blade 逻辑的内容:
{{ $slot() }}才能执行,否则啥也不输出 - 判断是否有内容?别用
@isset($slot)——它永远为 true。改用{{ $slot->isNotEmpty() }} - 空格或换行也算内容,
empty($slot)不可靠,$slot->toHtml() === ''更准
命名插槽和默认插槽混用时顺序和语法不能错
Laravel 要求具名插槽必须写在默认插槽之前,否则编译器可能报 Unexpected token;而且 <x-slot></x-slot> 的 name 值必须和组件内变量名完全一致(大小写敏感)。
- 正确顺序:
<x-slot name="header">...</x-slot>→ 再写主体内容 → 最后<x-slot name="footer">...</x-slot> - 错误写法:
<x-slot name="header">...</x-slot><x-slot name="footer">...</x-slot>{{ $slot }}→$slot会捕获到两个x-slot之间的空隙,导致主体内容丢失 - 别写成
<slot name="header"></slot>或@slot('header')——Laravel 10+ 只认<x-slot name="..."></x-slot> - 重复定义同名插槽(比如写了两次
<x-slot name="header"></x-slot>)会静默忽略,或在 Laravel 10+ 报Slot "header" already exists
怎么给插槽加 fallback 默认内容?
Blade 没有类似 Vue 的 slot="footer" fallback="..." 语法。默认内容必须手动控制,且方式因插槽类型而异。
- 默认插槽:
{{ $slot->default('加载中...') }}或{{ $slot->default(fn() => view('components.spinner')) }} - 命名插槽:
@isset($footer){{ $footer }}@else<small>暂无底部信息</small>@endisset - 别在
<x-slot name="footer">默认文字</x-slot>里写 fallback——那只是占位示意,父模板一传内容就全被覆盖 - 如果用了
@scope或scope: true,fallback 逻辑仍需写在组件内,作用域隔离不影响默认值判断
最容易被忽略的一点:每个容器型组件(比如 card、modal、form)都必须在其 Blade 文件里显式写出 {{ $slot }} 或 {{ $header }} 等变量输出语句;漏掉任何一个,对应内容就彻底消失,且不报错、不警告。


















