寫了好幾天,每天都在更正錯誤= =
blade 裡面太多類似的方法了,直接看 Laracasts 7 真的一頭霧水,去惡補完前幾代的 blade 才能理解。最好先了解一下 Laracel 5 的 component。
@extends + @section
功能上跟 @component + @slot
一樣
之後 @component + @slot
被 <x-component> + <x-slot>
取代
至於 <x-component />
看起來就是 @include
Laravel 7 前: @extends
透過 @extends('layout')
擴充 Layout,插入 footer 元件
@section + @yield
layout 裡面留一塊區塊給其他 blade 實作。當我們進入 page blade 時,因為 page 擴充 layout,所以看起來就像 layout,但是 @yield('content') 將呈現 @section('content') 包夾的內容。
page.blade
@extends('layout')
@section('content')
implements something
@endsection
layout.blade
@yield('content')
也可以使用 @component 寫法
@component + slot
要引用 component 的那個 blade 實作內容
<!-- /resources/my/oops-alert.blade.php -->
@component('alert')
<strong>Whoops!</strong> Something went wrong!
@endcomponent
component 寫好樣式用 slot 預留位置給其他 blade 插入內容
<!-- /resources/views/alert.blade.php -->
<div class="alert alert-danger">
{{ $slot }}
</div>
Laravel 7:用 x-component
取代 @component
- 必須將父視圖 layout.blade 放在 components 資料夾
- 要使用 php artisan make:component [name] 來建立 x-component
更正
其實不用 make:component 也可以,這樣就會變成匿名元件(anonymous compontn = 沒有綁 view model 的 component,有 view nodel 可以做更多資料操控)
我不知道為什麼之前做匿名元件都弄不出來,我真的不知道...
blade 只要遇到 x-component
就會去掃描 components 資料夾。(要有 view model render)
其實這樣 layout 叫父視圖也怪怪的。之前是用 @extends 擴充,所以叫父視圖沒什麼問題。但 layout 變成 component 感覺就像一個普通的個元件,被注入到 view page。心理上過不去,怪怪的。
x-component
+ {{ $slot }}
views 的 blade 實作注入 component
<!-- /resources/views/oops-alert.blade.php -->
<x-alert>
<strong>Whoops!</strong> Something went wrong!
</x-alert>
layout component 一樣用 slot 預留可以被注入的部分
<!-- /resources/components/alert.blade.php -->
<div class="alert alert-danger">
{{ $slot }}
</div>
<x-component>
+ <x-slot>
<x-componentName>
基本上就是之前的@component('componentName')
<x-slot name="var">
基本上就是之前的@slot('var')
content.blade
實作 HTML,並透過 <x-layout>
指定注入樣板 layout.blade
content.blade
裡,title="Laravel"
的 title 資料綁定 component 的{{ $title }}
變數呈現。content.blade
裡,<x-slot name="ad">
ad 綁定 component 的{{ $ad }}
content.blade
裡,沒有綁定變數的預設綁定給{{ $slot }}
的資料是由content.blade
提供,
注意
這邊如果 blade 想直接傳 title 變數給 component blade,component blade 必須是匿名的
否則必須在 view model 裡面設定 public variabel
resources/views/content.blade.php
<x-layout title="Laravel">
<x-slot name="ad">
Buy Me a Coffee
</x-slot>
Laravel 7 Blade Component Note
</x-layout>
resources/views/components/layout.blade.php
<div>
Hello {{ $title }}
</div>
<div>
@if( isset($ad) )
<div class="ad">
{{ $ad }}
</div>
@endif
<div class="dashboard">
{{ $slot ?? '' }}
</div>
<div>
組合 components
現在有一個 flash blade 是擴充 layout
檔案結構:
resources/views/
|-components //可注入的元件 blade
|---layout.blade.php
|-welcome.blade.php //視圖 blade
layout = HTML 結構檔案
{{ $slot }}
welcome = 注入 layout ,並實作 layout slot
<x-layout>
<section>
<p>一些提示訊息</p>
</section>
</x-layout>
但 welcome 裡面的東西是可以再做元件,因此我們再做一個 flash 元件:
檔案結構:
resources/views/
|-components //注入子視圖的元件
|---layout.blade.php
|---flash.blade.php
|-welcome.blade.php //子視圖
flash
<section>
<p>一些提示訊息</p>
</section>
welcome
<x-layout>
<x-flash></x-flash>
</x-layout>
這樣 welcome 就會透過 x- 去注入 layout,並實作 layout 的 slot。
welcom 實作又是用一個 x- ,所以它會注入 flash。flash 沒有需要實作的內容,最終呈現的畫面就是 flash 所寫的 <p>一些提示訊息</p>
。
props
之前我們傳入的變數都是直接使用雙括號顯示。例如 title="Laravel"
-> {{ $title }}
。
使用 props 可以傳入變數
flash
@props([
'type' => 'light'
])
<section class=" {{$type === 'dark' ? 'bg-black' : 'bg-gray-300'}} ">
<p>
{{ $slot }}
</p>
</section>
在 welcome 沒有傳入 type 時,props 設定 type 為 light 版面。
現在從 welcome 傳入 dark。結果就是 dark 版面。
welcome
<x-layout>
<x-flash type="dark">
flash~~
</x-flash>
</x-layout>
props 可以有更多的應用
flash
@props([
'type' => 'light',
'colors' => [
'light' => 'bg-gray-300',
'dark' => 'bg-black'
]
])
<section class="{{ $colors[$type] }}" >
<p>
{{ $slot }}
</p>
</section>
<x-component />
前面插來插去的,搞到最後都不知道是誰繼承,感覺在哪個地方實作都可以。這個寫法就比較清楚,component 裡面實作你的元件,view page 用 <x-component />
注入。
譬如這個寫死的 footer 元件要注入到 pages/home,就跟 @include 一樣好懂。
resources/views/components/footer.blade.php
<div>
default footer
<div>
resources/views/pages/home.blade.php
<x-footer />
一樣是可以做匿名元件
resources/views/components/footer.blade.php
<div>
{{ $title }} //laravel
<div>
resources/views/pages/home.blade.php
<x-footer title="laravel"/>
View Model ( Component Class )
透過 make:component DemoLayout
產生 app/View/Components/DemoLayout
、resources/views/components/demo-Layout.balde.php
demo-Layout
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class DemoLayout extends Component
{
/**
* Create a new component instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\View\View|string
*/
public function render()
{
return view('components.demo-layout');
}
}
實作 View Model 驅動畫面
header.php (extends Component)
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class Header extends Component
{
public $header; //
public function __construct($header)
{
$this->header = $header //
}
public function render()
{
return view('components.header');
}
}
header.blade.php
<div>
{{ $header }}
</div>
layout.blade.php
<x-header header="My website" />
inline blade
make:component text --inline
在 Component Class 直接 return blade view 就不用去 resources/views/components 找對應的檔案
Component Class 可以置換 attributes,也可以 merge
render()
{
return <<<'blade'
<div {{ $attrubutes->merge(['class' => 'bg-red-400 text-white']) }}>
{{ $description here }}
</div>
blade;
}
layout.blade 可以覆蓋 Component Class 寫的 style
<x-notify description="" class="bg-green-400" />
Component Class 也可以傳進其他東西例如 type
render()
{
return <<<'blade'
<div class="{{ $type === 'success' ? 'bg-green-400' : 'bg-red-400'}}"">
{{ $description here }}
</div>
blade;
}