Laravel Blade:@extend 一个(已经扩展的)子刀片?

Posted

技术标签:

【中文标题】Laravel Blade:@extend 一个(已经扩展的)子刀片?【英文标题】:Laravel Blade: @extend a (already extended) child blade? 【发布时间】:2016-01-25 11:36:06 【问题描述】:

谁知道是否可以延长儿童刀片?

我的应用程序有一个通用布局模板,然后每个页面都从该模板扩展而来。 每个页面都可以根据需要为其他 html 块(例如模式)引入一系列 @include。

@extends('common.layout')

@section('content')
    ... Some other content ...
    @include('modals.modal-1')
    @include('modals.modal-2')
@endsection

所有的模态都有很多通用的样板代码(Bootstrap),所以我想做的是定义一个主模型模板,让所有模态都@extend,然后在我的页面中@include必需的。所以 /modals/modal-1.blade.php 看起来像:

@extends('common.modals')

@section('modal-id', 'modal-1')
@section('modal-title','Modal title')

@section('modal-body')
    ... Some HTML / Blade here ...
@endsection

但每次我尝试时,生成的 HTML 都会损坏。在上述情况下,modal-1 将显示两次,因为它首先出现,而 modal-2 则根本不存在。翻转顺序,modal-2会出现两次。

我想我可以简单地将模态体放在一个变量中,并在@include 语句@include('modal.blade', ['body' => '<div>...</div>']) 中使用它,但使用@extends 感觉更正确。

有什么想法吗?

【问题讨论】:

【参考方案1】:

您绝对可以从已经扩展的视图中扩展 Blade 视图。但是,您将模板继承与视图包含混合在一起,这会导致奇怪的结果。

当使用@extend 指令继承模板时,您必须始终返回所需链上的最低子级。假设您有 3 代模板:

//grandparent.blade.php
<html>
<head>
    <title>My App</title>
</head>
<body>
    @yield('parent-content')
</body>
</html>

//parent.blade.php
@extends('grandparent')

@section('parent-content')
<div class="container">
    @yield('child-content')
</div>
@endsection

//child.blade.php
@extends('parent')

@section('child-content')
<div class="page">
    //stuff
</div>
@endsection

在这种情况下,您将返回子视图,它还将包含上面的两代模板。但是您可以永远返回 parent.blade.php 并期望它也返回该子视图。可能有 100 个子视图扩展了父视图,因此无法知道是哪一个。

@include 指令视为一种将视图中的HTML 很好地分解为更小的部分的方法。通常,您会将它用于要在多个视图中引用的可重用代码段。但是,它与模板继承不同。另请记住,包含的视图将获得与其父视图相同的所有数据(您甚至可以传递更多数据)。

在您的情况下,您必须决定什么构成了页面的基本根。页面的核心是modal-1?如果是这样,您需要从您的控制器返回modal-1作为您的子视图并将其向上延伸。在这种情况下,请保留与您在帖子中完全相同的文件。它的父视图 (common.modals) 需要更改为:

@extends('common.layout')

@section('content')
    ... Some other content ...

    @yield('modal-id')
    @yield('modals-title')
    @yield('modal-body')

    @include('modals.modal-2')
@endsection

显然,您会将这些 yield 语句中的每一个放在页面上有意义的位置。

但是,如果modal-1 不是页面的核心,而只是您想要包含的额外内容(例如小部件),那么您应该像您正在做的那样include在父视图中。在这种情况下,您需要从中删除 @extends 指令,并且不必费心将主 HTML 包装在任何部分中。它只会按原样传递给视图。如果您在包含的模板中包含部分,则必须在包含它的视图中屈服于这些部分。所以你的modal-1 模板最终看起来像这样:

<div>
    <p>HTML goes here. No need to extend anything or wrap in a section.
       You can still include $data though.
    </p>
</div>

@section('script')
    Including this section means that the view that is including this template
    already contains a @yield('script') directive.
    By including the @parent directive, this section will append that one.

@parent
@endsection

【讨论】:

【参考方案2】:

我相信包含已经扩展了其他一些模板的模板的正确方法是在包含的模板中使用@overwrite 代替@endsection

@extends('common.modals')

@section('modal-id', 'modal-1')
@overwrite
@section('modal-title','Modal title')
@overwrite

@section('modal-body')
    ... Some HTML / Blade here ...
@overwrite

【讨论】:

这实际上解决了我的问题。 请查看模板上的官方文档(包括子视图、覆盖部分):laravel.com/docs/5.0/templates。

以上是关于Laravel Blade:@extend 一个(已经扩展的)子刀片?的主要内容,如果未能解决你的问题,请参考以下文章

laravel-模板引擎Blade

TODO:Laravel 使用blade标签布局页面

在Sage 9的观点中,Laravel Blade的$ loop vairable是否可用?

我正在使用 Laravel + vue 通过 Blade 将变量传递给 vue 但它不显示

laravel5.1框架基础之Blade模板继承简单使用方法分析

使用 PhpUnit 测试在 Laravel 5 包中包含 @include 或 @extend 指令的刀片视图