最近 blade を使ったhtmlのコンポーネント化について調べたのでまとめます。
Laravel公式のbladeテンプレートのセクションにも記載があり、実用できそうでした。
サンプル
コンポーネントを/resources/views/components/attribute.blade.php
から呼び出すサンプルです。
resources/views/sample.blade.php
<div class="attribute-wrapper">
@component('components.attribute',
['attributeName'=>__("氏名"),
'required'=>true,
'attributeInfo'=> __("名前を入力してください")])
@endcomponent
</div>
/resources/views/components/attribute.blade.php
<div class="attribute-name">
<span>{{ $attributeName }}</span>
<div class="d-flex justify-content-between position-relative">
@if($required)
<div class="required ">{{ __('必須') }}</div>
@endif
<i class="fas fa-info-circle attribute-info-mark"></i>
<p class="attribute-info">{{ $attributeInfo }}</p>
</div>
</div>
cssとhtmlの記述をbladeで完結させたい
コンポーネント化をすすめていく中で、cssとhtmlの記述をbladeで完結させたいと思いつきました。
調べたところ@ push ディレクティブと、@ stackディレクティブを使うと
pushしたテンプレートをstackで取り出すことができるようです。
スタック
Bladeはさらに、他のビューやレイアウトでレンダできるように、名前付きのスタックへ内容を退避できます。子ビューで必要なJavaScriptを指定する場合に、便利です。
@push('scripts')
<script src="/example.js"></script>
@endpush
必要なだけ何回もスタックをプッシュできます。スタックした内容をレンダするには、@stackディレクティブにスタック名を指定してください。
<head>
<!-- Headの内容 -->
@stack('scripts')
</head>
laravel5.8公式ドキュメント(https://readouble.com/laravel/5.8/ja/blade.html)
コンポーネントのcssが複数回呼び出される
stackに登録したcssを呼び出すと、コンポーネントが複数回呼び出されている場合、複数の同じcssが登録されてしまいました。
解決方法として、Bladeファサードを使い、同一コンポーネントからの同じ要素のpushを防ぐ独自のディレクティブ pushonceを作成することで解決する方法を記載します。
1. pushonceディレクティブの登録
App\Providers\AppServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//
\Blade::directive('pushonce', function ($expression) {
$var = '$__env->{"__pushonce_" . md5(__FILE__ . ":" . __LINE__)}';
return "<?php if(!isset({$var})): {$var} = true; \$__env->startPush({$expression}); ?>";
});
\Blade::directive('endpushonce', function ($expression) {
return '<?php $__env->stopPush(); endif; ?>';
});
}
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
}
2. component毎にcssをpushする
resources\views\components\operations.blade.php
div class="operations-container status-bar">
{{ $slot }}
</div>
@pushonce('css')
<style>
.operations-container{
display: flex;
/* justify-content: space-evenly; */
flex-flow: row wrap;
align-content: space-around;
}
</style>
@endpushonce
pushonceの呼び出し方は、pushと全く同じです。
3. stackで css を呼び出す。
resources\views\layouts\app.blade.php
<body>
<main id="app">
<div class="main-container">
@yield('content')
</div>
</main>
</body>
@stack('css')
stackは通常の通りの呼び出しです。
これでコンポーネントのcssの重複呼び出しはなくなりました。
以上です。