【Laravel】Bladeで直書きJavaScriptのコンポーネントを作る時の勧め

著者:杉浦

【Laravel】Bladeで直書きJavaScriptのコンポーネントを作る時の勧め

BladeはシンプルながらパワフルなLaravelのテンプレートエンジンです。
Bladeテンプレート 5.7 Laravel

 BladeはLaravelで用いられるテンプレートエンジンであり、PHPの構文を書きやすく、読みやすい形でHTMLに埋め込みます。例えば

<?php if(auth()->guard('admin')->check()): ?>
  <div class="alert alert-danger">
    <?php echo e($slot); ?>

  </div>
<?php endif; ?>

ならばBladeでは

@auth('admin')
<div class="alert alert-danger">
    {{ $slot }}
</div>
@endauth

と記述できます。
 Bladeはコンポーネント指向――多数の部品を組み合わせることで完成品を作る考え――の元にwebページを作ることが出来ます。例えば、

@section('link_button')
    <a class="btn btn-primary font-weight-bold text-white" href="{{$link}}">
        {{$text}}
        <i class="fa fa-angle-right fa-lg right -pull-right"></i>
    </a>
@overwrite
@yield('link_button')

と定義すると

@include('link_button',['text'=>'hoge','link'=>'/hoge'])
@include('link_button',['text'=>'fuga','link'=>'/fuga'])
@include('link_button',['text'=>'foo','link'=>'/foo'])

と呼び出した時に/hoge, /fuga, /fooそれぞれに飛んでいくボタンの見た目のリンクが作られます。この仕組みはJavaScriptに応用できます。
 やり方はscriptタグを書いたコンポートを定義するだけです。例えば、

@section('alert_by_javascript')
<script>
    if (document.readyState !== 'loading') {
      alertHoge()
    } else {
      document.addEventListener('DOMContentLoaded', alertHoge);
    }
    function alertHoge(){
      alert({{$hoge}});
    }
</script>
@overwrite
@yield('alert_by_javascript')

と定義して

@include('alert_by_javascript',['hoge'=>'hoge'])
@include('alert_by_javascript',['hoge'=>'fuga'])
@include('alert_by_javascript',['hoge'=>'foo'])

 と呼び出すと、hoge, fuga, fooと文字列を表示するalertが発生します。パッと使うだけならこの通り簡単なのですが、注意点は素のJavaScriptを書いている点で問題点が発生します。深刻なのはグローバル汚染です。全て同じ階層にあるため他コンポーネントと変数名、関数名が被った時に容易にバグります。
 解決方法の一つは常に即時関数で囲みスコープを作ることです。こうするとコンポーネントの外に漏れることはありません。しかし、外部で使いたい時もあります。グローバル汚染を防ぎながら外部でJavaScriptを適宜呼び出せるようにする方法が次です。

@section('auto_redirect_to_top_script')
  @php
    // グローバル汚染回避のためにランダムな文字列か指定された文字列を名前に持つ関数を作る
    $function_name = $function_name ?? str_random();
  @endphp
  <script type="text/javascript">
    if (document.readyState !== 'loading') {
      {{$function_name}}();
    } else {
      document.addEventListener('DOMContentLoaded', {{$function_name}});
    }
    function {{$function_name}}(){
      alert({{$hoge}});
    }
  </script>
@overwrite
@yield('alert_by_javascript')

 関数の名前を呼び出す際に関数名を決めます。こうするとスコープは閉じたままで、外から任意に呼び出せます。

@include('alert_by_javascript',['hoge'=>'hoge','function_name' => 'hoge_function'])// hoge_function()が走る
@include('alert_by_javascript',['hoge'=>'fuga','function_name' => 'fuga_function'])// hoge_function()が走る
@include('alert_by_javascript',['hoge'=>'foo'])// `${ランダムな文字列}`()が走る

 この手法の注意点はやはり素のJavaScriptを書いている点です。古いIEを代表とするいくらかのブラウザは近年のJavaScriptの記述を読み取れず、実行できません。このコンポーネントに書かれているJavaScriptはほぼそのままwebページに表示されます。なんとなくで記述を行うといくらかのブラウザではJavaScriptを実行してくれません。他にも圧縮、難読化、コメントなど素のJavaScriptそのままならではの問題点が出てきます。

  • この記事いいね! (1)

著者について

杉浦 administrator