1. 定义布局
Blade 的两个主要优点是 **模板继承**
和**区块**
。为方便入门,让我们先通过一个简单的例子来上手。首先,我们来研究一个「主」页面布局。因为大多数 web 应用会在不同的页面中使用相同的布局方式,因此可以很方便地定义单个 Blade 布局视图:
@section : 定义了模板的内容
@yield : 显示指定的内容
<!-- 位于 resources/views/layouts/app.blade.php -->
<html>
<head>
<title>App Name - @yield('title')</title>
</head>
<body>
@section('sidebar')
This is the master sidebar.
@show
<div class="container">
@yield('content')
</div>
</body>
</html>
父页面显示的效果:
这里网页title只显示了 App Name - 说明了@yield()定义的内容不会显示出来,如果我稍作修改,给yield额外添加一个参数,第二个参数作为一个默认值会在 [yield] 片段未定义时被渲染出来
<title>App Name - @yield('title', 'fa')</title>
效果如下:
这是fa网页的渲染后的源码,@yield看起来像是一个占位符,它什么也没有做。
<!-- 位于 resources/views/layouts/app.blade.php -->
<html>
<head>
<title>App Name - fa</title>
</head>
<body>
This is the master sidebar.
<div class="container"></div>
</body>
</html>
2. 继承布局
在定义一个子视图时,使用 Blade 的 @extends 指令指定子视图要「继承」的视图。扩展自 Blade 布局的视图可以使用 @section 指令向布局片段注入内容。就如前面的示例中所示,这些片段的内容将由布局中的 @yield 指令控制显示:
<!-- 位于 resources/views/layouts/child.blade.php -->
@extends('layouts.app')
@section('title', 'Page Title')
@section('sidebar')
@parent
<p>This is appended to the master sidebar.</p>
@endsection
@section('content')
<p>This is my body content.</p>
@endsection
页面效果
我们通过观察可以发现 :
@extends指令是继承
@section(‘title’, ‘Page Title’) 修改了页面的标题使用了第二个参数作为默认值。
@parent 指令好像是追加内容
3. 测试
我发现通过官方手册你根本就不可能知道这些指令的作用,而且区别也分不清,脾气来了自己整理一下。参考:https://www.kancloud.cn/baidu/laravel5/30671
3.1 思考1:
@yield 定义的内容是不可以扩展的,子模板无法继承。@section既可以被替代,也可以被扩展。光这么说真的相当于没说,上代码。
demo1
先定义一个父模板
{{-- father --}}
{{-- 1.第一个参数只是定义一个区块的名称,作用和 @section类似 2.第二个参数是默认值,如果定义了就会显示 --}}
@section('title')
我是父页面定义的title <br>
@endsection
@yield('title','我是父页面的默认标题')
@section('content')
我是父页面的默认内容 <br>
@show
postman 访问
分析:lin5~line7 我们在父页面定义了 title 这个区块,如果将line7 的 @endsection 换成 @show name就会多出一行显示的内容 我是父页面定义的title,从字面意思上看,猜都可以猜出 @show是用来显示定义的区块内容的。由于我先定义了 title这个区块所以呢,下面的@yield是不会显示出默认内容的,再往下面页面会显示我定义的 ‘content’ ,如果@yield就是这样用在父页面,那也太没意思了。
demo2
定义一个子模板,继承上面的模板
{{-- child --}}
@extends('test.father')
@section('title')
@parent
我是子页面追加的title
@stop
@section('content')
@parent
我是子页面扩展的内容
@stop
postman 访问
demo3
这样看感觉也并不是很清楚,我们可以一步一步分析。现在我改变这个子模板文件,我就让它去继承父模板,然后什么也不干。代码入下:
{{-- child --}}
@extends('test.father')
{{--@section('title')--}}
{{-- @parent--}}
{{-- 我是子页面追加的title--}}
{{--@stop--}}
{{--@section('content')--}}
{{-- @parent--}}
{{-- 我是子页面扩展的内容--}}
{{--@stop--}}
postman 访问
分析:这里仅仅显示了两行内容,答案很明显了。继承后显示的是下面我打上√的部分,也就是说我们在父页面使用 @section 定义的区块,默认情况下通过继承子页面也是会显示到这些区块的,而@yield这个就不会。所以@yield不可被继承,没有扩展性,而@section是具有扩展性的,默认就是被子模板继承。
@section('title')
我是父页面定义的title <br> √
@endsection
@yield('title','我是父页面的默认标题') ×
@section('content')
我是父页面的默认内容 <br> √
@show
继续思考demo2的结果。我先给每一句编个号,然后分析一波,demo2 中的代码 执行到 line4 @section('title') ... ...
发现了可以从父页面继承这个title区块,于是编号1的结果就被打印了,然后在去解析的时候又发现 line5 **@parent**
line6 我是子页面追加的title
所以编号2的结果被追加打印了出来,由于没有换行符号,所以呢。解析子页面 line9 的代码时就接着在这一行显示喽,后面的继续先显示了继承自父页面的内容,然后追加了子页面自身的内容。
1.我是父页面定义的title
2.我是子页面追加的title 3.我是父页面的默认内容
4.我是子页面扩展的内容
3.2 思考2:
- @section 可以使用 @show、 @stop、 @overwrite、@append、@endsection 来结束,有什么区别?
@show 与 @stop
其实@section
的结束关键字在早期有这个@endsection
,不过在4.0的版本就已经被移除并且不建议使用了,虽然它是向下兼容的。@show
指的是执行到此处将 section 的内容输出到页面中,也就是显示。@stop
是只进行内容解析并且对这个 section 停止处理,除非使用 @override 来进行覆盖。通常来说,在首次定义某个 section 的时候,应该用 @show
,而在替换它或者扩展它的时候,不应该用 @show
,应该用 @stop
。
父页面
{{-- test.father2 --}}
<div id="zoneA">
@section('zoneA')
AAA
@show
</div>
<div id="zoneB">
@section('zoneB')
BBB
@stop
</div>
<div id="zoneC">
@section('zoneC')
CCC
@show
</div>
父页面显示情况
分析父页面:父页面的显示情况没啥说的,@show显示section定义的内容,@stop就不会显示喽。
子页面
{{-- test.child2 --}}
@extends('test.father2')
@section('zoneA')
aaa
@stop
@section('zoneB')
bbb
@stop
@section('zoneC')
ccc
@show
子页面显示情况
分析子页面:如果我注释子页面其他的内容,只是继承于父页面,代码如下
{{-- test.child2 --}}
@extends('test.father2')
显示的效果
网页的源码
<div id="zoneA">
AAA
</div>
<div id="zoneB">
</div>
<div id="zoneC">
CCC
</div>
zoneB 的内容丢失,因为没有用 @show
告诉引擎输出这部分的内容,而 zoneC 的内容会显示两次,并且还破坏了 因为 @show
出现了两次。如果想要在子页面追加内容就一定要使用@partent
指令,否则只是使用了@stop
就像是完全重写了父类的方法一样。使用@show
就一定会显示出来,所以。子模板如果继承父模板就使用@stop好了,如果想要追加内容,就在里面添加@parent
就好了。还是前面的那句话替换和扩展父模板使用@stop
,放弃@show
@append 和 @override
通过上一个例子我们分析出@stop
是在子模板中指明内容替换父模板的默认内容。它好像做了重写的事情,那么@override
干啥捏。这里涉及到了一个这样的问题:section在模板中是可以多次使用的问题,代码照搬。
父模板
{{-- father3 --}}
<div>
@yield('content')
</div>
访问父模板,页面什么都不会显示
子模板
{{-- child3 --}}
@extends('test.father3')
@section('content')
加一行内容<br>
@append
@section('content')
再加一行内容<br>
@append
@section('content')
加够了,到此为止吧。<br>
@stop
访问子模板
父模板没有显示这是意料之中的事情,子模板只是显示了两句话,网上的这个例子会将三句话都显示出来,应该是Larvel版本的问题,**@append**
就有扩展的意思,从此处接着扩展内容。
如果我改写一下代码,如下所示:这里我看例子上的 override无效换成了overwrite
{{-- child3 --}}
@section('content')
加一行内容
@append
@section('content')
再加一行内容
@append
@section('content')
加够了,结束吧
@stop
@section('content')
都不要了,我说的。
@overwrite
效果:什么也没有,可能还是Larvel版本的问题呢