
本文详解如何在 Laravel 中为多个独立 Blade 组件(如 div1.blade.php、div2.blade.php)分别定义并自动聚合其专属 JavaScript,确保主布局(main.blade.php)能正确渲染各组件 HTML 并合并所有 @section('script') 内容,避免脚本丢失或执行顺序错误。
本文详解如何在 laravel 中为多个独立 blade 组件(如 div1.blade.php、div2.blade.php)分别定义并自动聚合其专属 javascript,确保主布局(main.blade.php)能正确渲染各组件 html 并合并所有 `@section('script')` 内容,避免脚本丢失或执行顺序错误。
在 Laravel 的 Blade 模板系统中,@include 是静态引入子视图的便捷方式,但它不会自动继承或合并子视图中定义的 @section(如 @section('script'))。因此,当你在 div1.blade.php、div2.blade.php 等文件中各自声明 @section('script'),再通过 @include 引入到 main.blade.php 时,这些子节内容会被忽略——这是初学者常遇的核心陷阱。
✅ 正确解法是:改用 @extends + @yield 的继承机制,让所有组件(包括子组件)统一扩展同一个主布局,并由主布局集中 @yield('script')。这样,每个子视图通过 @section('script') 声明的脚本将被 Laravel 自动收集、追加并最终一次性输出。
✅ 推荐结构与代码实现
1. 定义主布局 resources/views/layouts/app.blade.php
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@yield('title', 'My App')</title>
@yield('style')
</head>
<body>
<main>
@yield('content')
</main>
<!-- 所有组件的 script 将在此处按声明顺序合并输出 -->
@yield('script')
</body>
</html>⚠️ 注意:@yield('script') 必须放在 </body> 闭合前,确保 DOM 已就绪,且脚本按子视图声明顺序执行(Laravel 默认累积追加)。
2. 创建可复用的组件视图(如 div1.blade.php)
{{-- resources/views/components/div1.blade.php --}}
@extend('layouts.app')
@section('content')
<div id="div1" class="component-div1">
<h3>Component 1</h3>
<button onclick="loadData1()">Fetch Data</button>
<div id="result1"></div>
</div>
@endsection
@section('script')
<script>
// ✅ 此脚本仅属于 div1,与其它组件隔离
function loadData1() {
fetch('/api/data1')
.then(res => res.json())
.then(data => document.getElementById('result1').textContent = data.message);
}
// 页面加载后自动初始化(可选)
document.addEventListener('DOMContentLoaded', () => {
console.log('div1 script loaded');
});
</script>
@endsection同理,div2.blade.php 和 div3.blade.php 各自 @extend('layouts.app') 并独立定义 @section('content') 与 @section('script')。
3. 主页面 main.blade.php —— 不再使用 @include,而是直接作为「组合页」
{{-- resources/views/main.blade.php --}}
@extend('layouts.app')
@section('title', 'Dashboard')
@section('content')
<header><h1>Dashboard</h1></header>
{{-- 直接渲染各组件视图(它们已继承同一布局) --}}
@include('components.div1')
@include('components.div2')
@include('components.div3')
{{-- 或更推荐:用 @each 或自定义组件封装逻辑 --}}
@endsection
@section('script')
{{-- 公共脚本(如全局工具函数、第三方库初始化)放在这里 --}}
<script>
console.log('Global scripts loaded');
// 例如:初始化全局事件总线、Axios 配置等
</script>
@endsection? 关键点:@include('components.div1') 在此上下文中仍会触发 div1.blade.php 中的 @section('script'),因为 div1.blade.php 本身是 @extend('layouts.app'),其 @section('script') 会被 Laravel 视为对父布局 @yield('script') 的填充内容——而 main.blade.php 作为当前渲染上下文,也参与了该 section 的累积过程。
✅ 运行效果与优势
- 最终 HTML 中,<script> 标签将按以下顺序输出:
<script>/* div1's script */</script> <script>/* div2's script */</script> <script>/* div3's script */</script> <script>/* main's common script */</script>
- 各组件脚本完全解耦:修改 div2.blade.php 的 JS 不影响 div1 的行为;
- 支持按需加载:可结合 Laravel Mix + @vite 或动态 import() 实现懒加载;
- 兼容 SEO 与 SSR:服务端直出完整 HTML + 脚本,无 hydration 冲突。
⚠️ 注意事项
- ❌ 不要混用 @include 和 @section 在非继承模板中——@include 是纯内容插入,不参与 section 生命周期;
- ✅ 若必须用 @include(如局部片段),请改用 @push('scripts') + @stack('scripts') 替代 @section(更灵活且支持多次追加);
- ? 对于高频复用组件,建议升级为 Blade Components(<x-div1 />),配合 @props 和内联脚本或 @once 防重复注册;
- ? 开发时启用 APP_DEBUG=true,检查浏览器控制台是否报错,并验证 Network 面板中脚本是否全部加载。
通过以上结构化设计,你不仅能精准控制每个 Blade 组件的专属逻辑,还能保持项目可维护性与扩展性——这才是 Laravel 模板系统的最佳实践之道。

















