Symfony環境でVue.jsを使う

ご無沙汰してます、光永です。
今回は技術記事です!ひさしぶりですね。
さっそくまいりましょう。

TL;DR

やりたかったこと

jQueryをやめてJSまわりをモダンにしたい。ただし、twigと共存するように。

やったこと

Vue.jsをDLしてフロント側で読み込むようにしたよ。
あと、twigで共存できるようにオプションをちょっとだけいじったよ。

やらなかったこと

vue-cliをつかったりとか.vueファイルを作ったりとかはしてないよ(twig内に書いただけだよ)
webpackも使ってないよ。
既存jQueryのものをどう置き換えるかみたいな話はしてないよ。
結局Bootstrap使ってたからjQueryの完全除去もしてないよ。

もとの環境

Symfony × jQuery × Bootstrap

ありがちだけどモダンではない。

完成後の環境

Symfony × jQuery × Bootstrap + Vue.js

要所要所Vueにしていこうね!!!っていう構成です。ちょっとずつね。

そもそもVue.jsとは?

MVVMパターンで設計されたコンパクトなJSのフレームワークです。
かるくてとってもはやく、動的にゴリゴリ動く画面を作るのに適してます。
あとは公式を見てね。

1. Vue.jsをフロントページにくみこむ

Vue.jsのファイルをダウンロードしてきて直接組み込みます。
オンラインで使うならCDNでもよい。
※開発バージョンと本番バージョンがあるので、開発時は開発バージョンを使うようにする。

{# @Hoge/layout.twig.html #}

{% block javascripts %}
    <script src="{{ asset('bundles/hoge/js/vue.js') }}">
    {#<script src="{{ asset('bundles/hoge/js/vue.min.js') }}">#}
{% endblock %}

2. オプションをカスタマイズ

Vueはtwigとデリミタ({{ }})が被っちゃってるんですよね。
なのでこれを変えます。
ここに書いてあるんですが、コンポーネントごとにやる必要があります。
ということでVueで実装する画面ごとに行う必要があるので要注意。
適宜共通化処理を書いた方がいいかもしれません。

{# @Hoge/Huga/index.twig.html #}

{% block javascripts %}
    {{ parent() }}
    <script>
        var app = new Vue({
            // デリミタはぶつからなければなんでもいいのです
            delimiters: ['{$', '$}']
        })
    </script>
{% endblock %}

最後. さっそくつかう

これだけです。かんたんですね。
弊社プロジェクトにおいてはjQueryとぶつかることもなかったので、このままどんどん使っていきましょう。

ちょっとだけサンプル

{# @Hoge/Huga/index.twig.html #}

{% block content %}
    <div id="app">
        {# Vue.jsだけ #}
        <ul>
            <li v-for="todo in todos">
                <input :id="'todo' + todo.no" type="checkbox" v-model="todo.done">
                <label :for="'todo' + todo.no">{$ todo.title $}</label>
            </li>
        </ul>

        {# まぜてみる #}
        {# twigの記述:サーバーサイドレンダリング
          →html(DOM):ブラウザ(1)
          →Vue.jsの記述(Virtual DOM):ブラウザ(2)
          という感じのレンダー順なので意識してやってみるとよさそう #}
        {% set todoNo = 2 %}
        TODO No.{{ todoNo }} は {$ getTodoToString({{ todoNo }}) $}
    </div>
{% endblock %}

{% block javascripts %}
    {{ parent() }}
    <script>
        var app = new Vue({
            el: '#app',
            delimiters: ['{$', '$}'],
            data: {
                todos: [
                    {no:1, title:'todo1', done: false},
                    {no:2, title:'todo2', done: true},
                ]
            },
            methods: {
                getTodoToString: function (todoNo) {
                    var todo;
                    for (var i=0; i<this.todos.length; i++) {
                        todo = this.todos[i];
                        if (todo.no != todoNo) {
                            continue;
                        }
                        if (todo.done) {
                            return '完了しています。';
                        } else {
                            return '未完了です。';
                        }
                    }

                    return '存在しません。'
                },
            }
        })
    </script>
{% endblock %}

実行するとこんな感じです
181210_ブログメモ

無事動いたところで、以上です。
Vue.jsが思ったより簡単に既存システムに入れていけることがお分かりいただけたかとおもいます。
それが目的でした。(うそ)

光永でした!
ではまた~~。