Laravel Blade组件需严格匹配命名与注册路径:文件名转kebab-case为标签名,子目录须手动注册;props须显式声明或用$attributes;slot需{{ $slot }}输出;组件内不可直接访问$loop、$errors等父级变量。

Blade组件命名和注册位置必须匹配
自定义组件在 Laravel 中不是“写完就能用”,它依赖严格的命名约定和注册路径。Laravel 会自动扫描 resources/views/components/ 下的文件,把文件名(不带扩展)转成 kebab-case 作为组件标签名。比如 resources/views/components/alert-banner.blade.php 对应 <x-alert-banner>。
常见错误是:文件放在 resources/views/components/ui/alert.blade.php 却直接用 <x-alert> —— Laravel 默认不递归扫描子目录,除非你显式注册。
- 若组件在子目录(如
ui/),必须在AppServiceProvider::boot()中调用Blade::component()手动注册:Blade::component('components.ui.alert', 'alert'); - 组件类名(如果用 class-based 组件)必须与文件名一致,且类需继承
Illuminate\View\Component - 避免使用下划线
_命名文件,Laravel 会把它转成连字符,但容易引发混淆(my_component.blade.php→<x-my-component>,而非<x-my_component>)
props 传参必须显式声明或使用 $attributes
Blade 组件接收数据不是靠全局变量或魔术方法,而是靠明确的 props 声明(class-based)或 $attributes(anonymous blade)。漏掉声明会导致参数“消失”——页面不报错,但值为空。
比如你传了 <x-button color="danger">Delete</x-button>,但在组件里没声明 public string $color,那 $color 就是 null;而用 $attributes->get('color') 能兜底取到,但不会自动绑定到变量。
- class-based 组件中,所有需要解构的 props 必须在构造函数参数 + public 属性中同时出现(Laravel 10+ 支持属性提升,可简写为
public function __construct(public string $color, public bool $outline = false) {}) - anonymous 组件(.blade.php 文件)无法自动解构 props,只能用
$attributes或$slot,想用$color?得手动写@props(['color' => 'default']) -
@props的默认值只在 anonymous 组件里生效,class-based 组件默认值要写在构造函数参数里
slot 内容不能直接 echo,要用 {{ $slot }} 或 @isset($slot)
很多人以为 slot 是“自动插入”的,结果发现子内容没渲染,或者报 Undefined variable: slot。根本原因是:slot 不是全局变量,它只在组件作用域内以变量形式存在,且必须显式输出。
更隐蔽的问题是空 slot 导致布局错乱——比如一个卡片组件期望有标题和正文,但调用时没传任何内容,{{ $slot }} 会输出空字符串,可能撑不开容器。
- 安全输出:用
@isset($slot){{ $slot }}@endisset包裹,避免空值干扰结构 - 具名 slot(如
<x-card><x-slot name="header">...</x-slot></x-card>)必须在组件内用{{ $header ?? '' }}或@if (isset($header)){{ $header }}@endif,不能直接{{ $slot }} - 不要在组件里对
$slot做trim()或strip_tags()—— 它可能是带 HTML 的完整子视图,随意处理会破坏语义
组件内不能用 $loop 或 $errors 等视图共享变量
Blade 组件运行在独立的作用域里,父模板传进来的 $loop、$errors、$request 等变量默认不可见。这不是 bug,是设计使然:组件要隔离上下文,否则复用性就垮了。
典型症状:在组件里写 @error('email'){{ $message }}@enderror,永远不显示错误——因为 $errors 没传进来。
- 需要访问
$errors?必须显式传入:<x-input-error :errors="$errors" field="email" />,并在组件里声明public $errors和public $field -
$loop同理,不能指望组件自动感知外层循环,得靠 props 传:loop="$loop" - 全局辅助函数(如
route()、url())可用,但依赖请求上下文的(如old())必须确认当前请求已存在,否则返回 null


















