LoginSignup
0

More than 3 years have passed since last update.

LaravelのBladeテンプレートをVue.jsっぽく書いてみた

Posted at

はじめに

Vue.jsを学習した時に、Vueコンポーネントのコード構成が非常に気に入りました。
そこで、LaravelのBladeテンプレートでも同様のコード構成ができるか検討してみたんですよね。
すると、自分の中では割と納得のいく形にできたんですよ。
なので、今回は私がLaravelのBladeテンプレートで採用したコード構成の例を紹介します:grinning:
※Vue.jsのベストプラクティスということではないので、誤解しないようにお願いします。

この記事の対象者

  • Laravelを学習されている方
  • Bladeテンプレートの書き方のサンプルが欲しい方

作業環境

コンピュータ : Mac mini(2018)
OS : macOS Catalina バージョン10.15.7
仮想基盤 : Docker version 19.03.8
ベースイメージ : AmazonLinux2
言語 : PHP7.4.11
フレームワーク : Laravel Version 6.20.5

Vue.jsのコード構成について

Vue.jsでは、コンポーネント(構成要素や部品の意)を作成する際に、HTML、CSS、Javascriptを1つのファイルに記述します。

page_titleコンポーネント

page_title.vue
<!-- HTML記述部-->
<template>
  <h1>{{title}}</h1>
</template>

<!-- Javascript記述部-->
<script>
export default {
    data(){
        return {
            title: "ページの大見出しだよ"
        }
    }
}
</script>

<!-- CSS記述部-->
<style>
  h1{ color: red; }
</style>

page_titleコンポーネントを呼び出す親コンポーネント

body.vue
<template>
    <!-- ここでは、読み込んだコンポーネントをタグとして利用しています -->
    <PageTitle></PageTitle>
    <!-- コンポーネントの読み込みは下のscriptタグ内で行っています -->
</template>

<script>
// ここで、pageタイトルコンポーネントを読み込んでいます。
import PageTitle from 'page_title.vue'

export default {
  components: {
    PageTitle
  }
}
</script>

表示されたページ

スクリーンショット 2020-11-29 6.29.19.png

Laravel(Bladeテンプレート)のコード構成

Laravelでは、Bladeテンプレートでディレクティブと呼ばれる記述方法を使用できます。
今回は、@include@yield@section等のディレクティブを利用してVueコンポーネントの用にBladeテンプレートを作成します。

page_title.vueの代替

page_title.blade.php
<!-- HTML記述部 -->
@section('page_title_template')
  <h1 id="page_title">title</h1>
@endsection


<!-- Javascript記述部 -->
@section('page_title_js')
  <script type="text/javascript">

    // windowロード時に呼び出す関数のセット
    window.onload = setH1InnerText;

    // windowロード時にh1タグのテキストを書き換える
    function setH1InnerText(){
      let h1_tag = document.getElementById('page_title');
      h1_tag.innerText = "ページの大見出しだよ";
    }

  </script>
@endsection


<!-- CSS記述部 -->
@section('page_title_css')
  <style>
    h1{ color: red; }
  </style>
@endsection

body.vueの代替

body.blade.php
<!-- ここでpage_title.blade.phpを読み込み -->
@include('page_title')
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@200;600&display=swap" rel="stylesheet">

        <!-- CSSの呼び出し -->
            @yield('page_title_css')

    </head>
    <body>
        <!-- HTMLの呼び出し -->
        @yield('page_title_template')

        <!-- Javascriptの呼び出し -->
        @yield('page_title_js')
    </body>
</html>

Laravelでは、親ファイルで子コンポーネントのCSSも明記する必要はありますね。

ホームを部品化してみよう!!

試しに、この構成を利用してLaravelのデフォルトホーム(Welcomeページ)を部品化してみます。

LaravelのWelcomeページのコード

welcom.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@200;600&display=swap" rel="stylesheet">

        <!-- Styles -->
        <style>
             html, body {
                background-color: #fff;
                color: #636b6f;
                font-family: 'Nunito', sans-serif;
                font-weight: 200;
                height: 100vh;
                margin: 0;
            }

            .full-height {
                height: 100vh;
            }

            .flex-center {
                align-items: center;
                display: flex;
                justify-content: center;
            }

            .position-ref {
                position: relative;
            }

            .top-right {
                position: absolute;
                right: 10px;
                top: 18px;
            }

            .content {
                text-align: center;
            }

            .title {
                font-size: 84px;
            }

            .links > a {
                color: #636b6f;
                padding: 0 25px;
                font-size: 13px;
                font-weight: 600;
                letter-spacing: .1rem;
                text-decoration: none;
                text-transform: uppercase;
            }

            .m-b-md {
                margin-bottom: 30px;
            }
        </style>
    </head>
    <body>
        <div class="flex-center position-ref full-height">

            <div class="content">
                <div class="title m-b-md">
                    Laravel
                </div>

                <div class="links">
                    <a href="https://laravel.com/docs">Docs</a>
                    <a href="https://laracasts.com">Laracasts</a>
                    <a href="https://laravel-news.com">News</a>
                    <a href="https://blog.laravel.com">Blog</a>
                    <a href="https://nova.laravel.com">Nova</a>
                    <a href="https://forge.laravel.com">Forge</a>
                    <a href="https://vapor.laravel.com">Vapor</a>
                    <a href="https://github.com/laravel/laravel">GitHub</a>
                </div>
            </div>
        </div>
    </body>
</html>

正直、長いですよね:sweat_smile:

ブラウザで表示

スクリーンショット 2020-11-29 8.14.37.png

部品化した場合のWelcomeページのコード

welcome.blade.php
<!-- コンポーネントの読み込み -->
@include('view_components.common_all_page_css')
@include('view_components.title')
@include('view_components.links')
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@200;600&display=swap" rel="stylesheet">

        <!-- Styles -->
            <!-- 全てのページ共通のCSS -->
            @yield('common_all_page_css')

            <!-- タイトル部分のCSS -->
            @yield('title_css')

            <!-- リンク部分のCSS -->
            @yield('links_css')
    </head>
    <body>
        <div class="flex-center position-ref full-height">

            <div class="content">
                <!-- タイトル部分のHTML -->
                @yield('title_template')

                <!-- リンク部分のHTML -->
                @yield('links_template')

          
         <!-- Jarascript -->
                @yield('title_js')
            </div>
        </div>
    </body>
</html>

次の3つのコンポーネントに分割しました

全ページ共通のCSSコンポーネント

common_all_page_css.blade.php
@section('common_all_page_css')
  <style>
    html, body {
      background-color: #fff;
      color: #636b6f;
      font-family: 'Nunito', sans-serif;
      font-weight: 200;
      height: 100vh;
      margin: 0;
  }

  .full-height {
      height: 100vh;
  }

  .flex-center {
      align-items: center;
      display: flex;
      justify-content: center;
  }

  .position-ref {
      position: relative;
  }

  .top-right {
      position: absolute;
      right: 10px;
      top: 18px;
  }

  .content {
      text-align: center;
  }
  </style>
@endsection

タイトル部分のコンポーネント

title.blade.php
@section('title_template')
  <div id="page_title" class="title m-b-md">

  </div>
@endsection

@section('title_js')
<script type="text/javascript">
  // windowロード時に呼び出す関数のセット
  window.onload = setPageTitleInnerText;

// windowロード時にタイトルのテキストを書き換える
function setPageTitleInnerText(){
  let page_title = document.getElementById('page_title');
  page_title.innerText = "Laravel";
}
</script>
@endsection


@section('title_css')
  <style>
    .title {
        font-size: 84px;
    }
    #page_title{
      color: green;
    }
  </style>
@endsection

ついでなので、CSSでタイトルの文字色を緑色にしてみました。
まぁ、タイトル文字をJSで代入することはありませんが、あくまでコード構成の例ですのでそこは参考程度に。

リンク部分のコンポーネント

links.blade.php
@section('links_template')
<div class="links">
    <a href="https://laravel.com/docs">Docs</a>
    <a href="https://laracasts.com">Laracasts</a>
    <a href="https://laravel-news.com">News</a>
    <a href="https://blog.laravel.com">Blog</a>
    <a href="https://nova.laravel.com">Nova</a>
    <a href="https://forge.laravel.com">Forge</a>
    <a href="https://vapor.laravel.com">Vapor</a>
    <a href="https://github.com/laravel/laravel">GitHub</a>
</div>
@endsection


@section('links_css')
<style>
  .links > a {
    color: #636b6f;
    padding: 0 25px;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: .1rem;
    text-decoration: none;
    text-transform: uppercase;
  }
</style>
@endsection

ブラウザで表示

スクリーンショット 2020-11-29 9.18.57.png

無事、タイトルが緑色のWelcomeページが表示されました。

最後に

LaravelのBladeテンプレートでは、1ファイル内に1つの@sectionを使用するのが基本のように見受けられます。
なので、今回のコード構成はパフォーマンス面で不都合があるのかもしれません。
とはいえ、恐らく、Laravelだけでサービスを開発する場合は、あまり影響がないと思っています。
そこまでパフォーマンスを求めるサービスをLaravelだけで開発することは珍しいでしょうからね:sweat_smile:

この記事が誰かのお役に立てると嬉しいです。
それでは、最後まで読んでいただきありがとうございます:blush:

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
0