LoginSignup
4
4

More than 3 years have passed since last update.

Vue.jsを参考に、BladeファイルにJavaScript, CSSをまとめてみる。

Last updated at Posted at 2020-01-14

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しない
resources/
- 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ファイルと同じディレクトリ構成とします。

resources/
- js
    - modules/
        - confirm
    - layouts/
        - app
        - parts/
            - header
    - ...

- sass
    - layouts/
        - app
        - parts/
            - header
    - ...

Bladeファイルに、JavaScriptとCSSを記述する。

まず、レイアウトファイル

layout/app.blade.php
<!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するファイル

layouts/parts/header.blade.php
@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を利用します。

layout/app.blade.php
<head>
  (省略)

  {{-- include先のcssファイルがここに追加される --}}
  @stack('css')
</head>

<body>
  (省略)

  {{-- include先のJSファイルがここに追加される --}}
  @stack('js')
</body>
layouts/parts/header.blade.php
@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が読み込まれてしまいます。

home/index.blade.php
  // deleteボタンを複数回includeすると回数分JavaScript, CSSが読み込まれる。
  @include('parts.buttons.delete')
  @include('parts.buttons.delete')
  @include('parts.buttons.delete')

ですので、1度だけ読み込むように、カスタムディレクティブを設定します。
参考: bladeのcomponent化による再利用

app/Providers/AppServiceProvider.php
/**
 * 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; ?>';
    });
}
layouts/parts/header.blade.php
@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

layout/app.blade.php
<head>
  (省略)

  // ここだとinclude先のファイルが反映されない
  {{-- @stack('css') --}}
</head>

<body>
  (省略)

  {{-- include先のcssファイルがここに追加される --}}
  @stack('css')

  {{-- include先のJSファイルがここに追加される --}}
  @stack('js')
</body>

これで、include先のファイルも反映されるようになります。

なお、CSSは原則そのファイルにしかスタイルが適用されないよう、
スコープを限定するように記載します。

home/index.scss

// 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

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4