Vue.jsの開発者的メリット
- HTML, JavaScript, CSSを1つのファイルに記述するというのがシンプルで良い
- scopedが便利
- コードが複雑化しにくい
そして思ったのです。
これって普通のアプリケーションにある程度応用できそう。
実際に考えてみる
ちょっと考えてみました。方針としては、
- 仕様に応じてBladeのディレクトリ構成をシンプルに考える
- JavaScript, CSSはBladeのディレクトリ構成に合わせる。
- 影響範囲は対応するBladeファイル内にとどまるように気をつける。
Bladeファイルのディレクトリ構成
サンプルです。実際には画面仕様などにより異なるはずです。
- ルール
- views/直下は、layouts/および、メニューに対応するディレクトリ(menus/を作ろうと思ったが階層が深くなりすぎるのが嫌なので却下)
- メニューごとのディレクトリには、ページに対応するbladeファイルがある
- メニューごとのディレクトリには、parts/があり、ページを構成する部品を格納する。
- formやbuttonなどの部品はparts/に格納する。
- ページに対応するファイルからは、parts/配下のファイルをincludeする。
- parts/配下のファイルからは、parts/配下のファイルををincludeする
- ページに対応するファイルから、parts/配下の部品をincludeしない
- 同階層のファイルをincludeしない
- views/
- layouts/
- app
- parts/
- header
- footer
- home/
- index
- parts/
- eye_catching
- new_product
- product/
- index
- show
- edit
- parts/
- product
- details
- account/
- show
- edit
- parts/
- table
- parts/
- forms/
- radio
- checkbox
- buttons/
- search
- submit
- delete
- flash_message
JavaScriptとCSS(Sass)は、Bladeファイルと同じディレクトリ構成
JavaScript, CSS(Sass)はBladeファイルと同じディレクトリ構成とします。
- js
- modules/
- confirm
- layouts/
- app
- parts/
- header
- ...
- sass
- layouts/
- app
- parts/
- header
- ...
Bladeファイルに、JavaScriptとCSSを記述する。
まず、レイアウトファイル
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
{{-- CSRF Token --}}
<meta name="csrf-token" content="{{ csrf_token() }}">
{{-- title --}}
<title>@yield('title', 'laravel app')</title>
{{-- 対応するCSSファイル --}}
<link rel="stylesheet" href="{{ mix('css/layouts/app.css') }}">
{{-- include先のcssファイルがここに追加される --}}
@yield('css')
</head>
<body>
@include('layouts.parts.header')
<div id="container">
@yield('content')
</div>
@include('layouts.parts.footer')
{{-- 対応するJSファイル --}}
<script src="{{ mix('js/layout/app.js') }}"></script>
{{-- include先のJSファイルがここに追加される --}}
@yield('js')
</body>
</html>
そして、includeするファイル
@section('css')
<script src={{ mix('/js/layouts/parts/header.css') }}>
@endsection
@section('js')
<script src={{ mix('/js/layouts/parts/header.js') }}>
@endsection
<header>
<div>ヘッダー</div>
</header>
これでOKと思ったのですが、これでは、include先に記述されたJavaScript, CSSが反映されません。
そこで@stack - @pushを利用します。
<head>
(省略)
{{-- include先のcssファイルがここに追加される --}}
@stack('css')
</head>
<body>
(省略)
{{-- include先のJSファイルがここに追加される --}}
@stack('js')
</body>
@push('css')
<script src={{ mix('/js/layouts/parts/header.css') }}>
@endpush
@push('js')
<script src={{ mix('/js/layouts/parts/header.js') }}>
@endpush
<header>
<div>ヘッダー</div>
</header>
これで、include先で記述されたJavaScript, CSSファイルが反映されるようになりました。
ただし、同じファイルを複数回includeすると回数分JavaScript, CSSが読み込まれてしまいます。
// deleteボタンを複数回includeすると回数分JavaScript, CSSが読み込まれる。
@include('parts.buttons.delete')
@include('parts.buttons.delete')
@include('parts.buttons.delete')
ですので、1度だけ読み込むように、カスタムディレクティブを設定します。
参考: bladeのcomponent化による再利用
/**
* 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; ?>';
});
}
@pushonce('css')
<script src={{ mix('/js/layouts/parts/header.css') }}>
@endpushonce
@pushonce('js')
<script src={{ mix('/js/layouts/parts/header.js') }}>
@endpushonce
<header>
<div>ヘッダー</div>
</header>
レイアウトファイルも少し修正します。
includeする前に@stackを記述するとその時点では、pushされるファイルがないので、
include先のファイルが反映されません。
そのため、bodyの閉じタグの直前に記述します。(ここは少し悩ましいところです。。。)
参考: Blade Stacks in Sub-View
<head>
(省略)
// ここだとinclude先のファイルが反映されない
{{-- @stack('css') --}}
</head>
<body>
(省略)
{{-- include先のcssファイルがここに追加される --}}
@stack('css')
{{-- include先のJSファイルがここに追加される --}}
@stack('js')
</body>
これで、include先のファイルも反映されるようになります。
なお、CSSは原則そのファイルにしかスタイルが適用されないよう、
スコープを限定するように記載します。
// home/index.blade.php
// <div class="home-index">
// <div class="test-class">
// コンテンツ
// </div>
// </div>
.home-index { // スコープを限定する
.test-class {
}
}
以上です。
参考
bladeのcomponent化による再利用
Blade Stacks in Sub-View
Blade Templates