@push 是 Laravel Blade 模板引擎中的一个指令,用于将内容推送到命名堆栈中,与 @stack 指令配合使用。

基本概念

@stack

  • 定义一个可以接收内容的"堆栈"区域
  • 通常放在布局模板中

@push

  • 向指定的堆栈推送内容
  • 可以多次调用,内容会按推送顺序排列

基本语法

{{-- 在布局文件中定义堆栈 --}}
@stack('stack-name')

{{-- 在子视图中推送内容 --}}
@push('stack-name')
    <!-- 推送的内容 -->
@endpush

使用示例

1. 基础使用

布局文件:layouts/app.blade.php

<!DOCTYPE html>
<html>
<head>
    <title>App</title>
    @stack('styles')
</head>
<body>
    @yield('content')
    
    @stack('scripts')
</body>
</html>

子视图文件:home.blade.php

@extends('layouts.app')

@section('content')
    <h1>Home Page</h1>
@endsection

@push('styles')
    <link rel="stylesheet" href="/css/home.css">
@endpush

@push('scripts')
    <script src="/js/home.js"></script>
@endpush

2. 多页面使用场景

多个页面向同一个堆栈推送内容

page1.blade.php

@extends('layouts.app')

@push('scripts')
    <script src="/js/page1.js"></script>
@endpush

page2.blade.php

@extends('layouts.app')

@push('scripts')
    <script src="/js/page2.js"></script>
    <script>
        console.log('Page 2 loaded');
    </script>
@endpush

最终 @stack('scripts') 会按推送顺序渲染所有内容。

高级用法

1. 推送变量内容

@php
    $scriptPath = config('app.env') === 'production' 
        ? '/js/app.min.js' 
        : '/js/app.js';
@endphp

@push('scripts')
    <script src="{{ $scriptPath }}"></script>
@endpush

2. 条件推送

@if($needsChart)
    @push('scripts')
        <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    @endpush
@endif

3. 内联推送(Blade 8.x+)

@push('scripts', '<script>console.log("inline")</script>')

4. 推送前预置内容

{{-- 在布局中先定义一些默认内容 --}}
@stack('styles')
    <link rel="stylesheet" href="/css/default.css">
@endstack

{{-- 子视图中会追加到默认内容之后 --}}
@push('styles')
    <link rel="stylesheet" href="/css/custom.css">
@endpush

与其他指令的对比

@push vs @section

{{-- @section 用于替换整个区块 --}}
@section('sidebar')
    @parent {{-- 保留父模板内容 --}}
    <p>Additional content</p>
@endsection

{{-- @push 总是追加内容 --}}
@push('scripts')
    <script>/* 总是添加 */</script>
@endpush

@push vs @include

{{-- @include 包含完整文件 --}}
@include('partials.scripts')

{{-- @push 推送特定内容块 --}}
@push('scripts')
    <!-- 特定代码 -->
@endpush

实际应用场景

1. 页面特定CSS/JS

{{-- 只在某些页面加载特定资源 --}}
@push('styles')
    <style>
        .page-specific {
            color: red;
        }
    </style>
@endpush

2. 动态组件脚本

{{-- 组件文件 --}}
<div id="component-{{ $id }}">Component Content</div>

@push('scripts')
    <script>
        document.getElementById('component-{{ $id }}').addEventListener('click', function() {
            // 组件逻辑
        });
    </script>
@endpush

3. Meta标签管理

{{-- 布局文件 --}}
<head>
    <meta charset="UTF-8">
    @stack('meta')
</head>

{{-- 子视图 --}}
@push('meta')
    <meta name="description" content="{{ $pageDescription }}">
    <meta property="og:title" content="{{ $pageTitle }}">
@endpush

最佳实践

  1. 命名规范:使用有意义的堆栈名称

    @stack('header-scripts')
    @stack('footer-scripts')
    @stack('inline-styles')
    
  2. 避免重复:确保相同的脚本不会被多次推送

    @unless(in_array('chartjs', $loadedScripts))
        @push('scripts')
            <script src="/chartjs.js"></script>
        @endpush
        @php $loadedScripts[] = 'chartjs'; @endphp
    @endunless
    
  3. 性能优化:合并推送内容

    @push('scripts')
        <script>
            // 页面初始化代码
            $(document).ready(function() {
                {{-- 多个初始化操作合并 --}}
                initTable();
                initChart();
                initForm();
            });
        </script>
    @endpush
    

注意事项

  1. 作用域@push 内容在堆栈被渲染时才输出
  2. 顺序:推送顺序就是渲染顺序
  3. 嵌套:可以在 @include 的文件中使用 @push
  4. 性能:过多的推送可能影响性能,考虑合并内容

通过 @push@stack 的组合,可以创建灵活、可维护的模板结构,特别适合需要动态添加CSS、JavaScript或HTML片段的场景。