日頃の行い

個人的な日頃の行いをつらつら書いてます\\\\ ٩( 'ω' )و ////

Vue.jsとjQueryを使った時の違いについて考えてみる。

この記事は Vue.js Advent Calendar 2014 - Qiita の21日分として書かれています。

めっちゃ遅れました。すみません(´・ω・`)

今、管理画面にVue.jsを使うか、React.jsを使うか、その他を使うか悩んでるので、この機能が便利かどうかを確認してみようかと思います。

最近ほんとにHTMLを書きたくないです。
最低限のテンプレートを定義して、データのモデルを渡したら描画してくれるような感じがいいです。
なので、フロントサイドのjsフレームワークを何か試したいと思いました。
データを表示するくらいならjQueryでもよくね。って思いが拭えないので、ちょっと考えてみようかと思います。


テーマはよくあるTODO一覧を表示するアプリです。

f:id:arata3da4:20141223022101p:plain

こんなアプリを書く時に楽かどうか考えてみたいです。

jQuery

まずは、jQueryで書いてみようかとともいます。

View (HTML)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="/css/bootstrap.css">
        <link rel="stylesheet" href="/css/bootstrap-theme.css">
    </head>
    <body>
        <div id="vueadvent" class="container"></div>
        <button type="button" class="btn btn-default" id="reflesh">更新</button>
    </body>

    <script type="text/javascript" charset="UTF-8" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
    <script type="text/javascript" charset="UTF-8" src="js/app-jquery.js"></script>
</html>

app.js

(function($) {
    var table = $("<table>").addClass('table');

    $.prototype.appendHeader = function(headers) {
        var thead = $("<thead>"),
            tr = $("<tr>");

        for(i=0; i < headers.length;i++) {
            tr.append($("<th>").text(headers[i]));
        }
        thead.append(tr);
        this.append(thead);
    };

    jQuery.prototype.appendBody = function(data) {
        var tbody = $("<tbody>");

        for(i_all = 0; i_all < data.length;i_all++) {
            var tr = $("<tr>");
            for (var prop in data[i_all] ) {
                var td = $("<td>").text( data[i_all][prop] );
                tr.append(td);
            }
            tbody.append(tr);
        }
        tbody.append(tr);
        this.append(tbody);
    };

    jQuery.prototype.appendData = function (headers, data) {
        table = $("<table>").addClass('table');
        this.appendHeader(headers);
        this.appendBody(data);
        return this;
    };
    var headers = [
        'title',
        'description'
    ];

    var reflesh = function() {
        $.ajax({
            url: '/todo',
        }).done(function(data){
            $("#vueadvent").empty();
            $("#vueadvent").append(table.appendData(headers,  data));
        }).error(function(data) {
            console.log(data);
        });
    };

    $(document).on('click',"#reflesh",function(){
        reflesh();
    });

    reflesh();

}).call(this, jQuery);

だいたいこんな感じかなぁと思います。
ほぼほぼjs側で書いて、どうにかするという形になりますね。
テンプレート情報の定義もjsでやらないといけなくなりますね。
次はVue.jsで書いてみようと思います。

Vue.js

View

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="/css/bootstrap.css">
        <link rel="stylesheet" href="/css/bootstrap-theme.css">
    </head>
    <body>
        <div id="vueadvent" class="container">
            <data-table v-with="
            data      : gridData,
            columns   : gridColumns
            "></data-table>
            <button type="button" class="btn btn-default" v-on="click: reflesh" >更新</button>
        </div>
    </body>

    <!-- component template -->
    <script type="text/x-template" id="data-template">
        <table class="table">
            <thead>
                <tr>
                    <th v-repeat="key: columns">
                        {{key | capitalize}}
                    </th>
                </tr>
            </thead>
            <tbody>
                <tr v-repeat="entry: data">
                    <td v-repeat="key: columns">
                        {{entry[key]}}
                    </td>
                </tr>
            </tbody>
        </table>
    </script>
    <script type="text/javascript" charset="UTF-8" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
    <script type="text/javascript" charset="UTF-8" src="js/vue.js"></script>
    <script type="text/javascript" charset="UTF-8" src="js/app.js"></script>
</html>

app.js

(function() {

    Vue.component('data-table', {
        template: '#data-template',
        data: function () {
            return {
                columns: null,
            }
        }
    })

    var advent = new Vue({
        el: "#vueadvent",
        data: {
            gridColumns: ['title', 'description'],
            gridData: []
        },
        methods : {
            reflesh: function() {
                var self = this;
                $.ajax({
                    url: '/todo',
                }).done(function(data){
                    self.gridData = data;
                }).error(function(data) {
                    console.log(data);
                });
            }
        }
    })
    advent.reflesh();

    return advent;
}).call(this);

Viewの方にある程度データを移せたように思えます。
javascriptがやっていることは、
・どれをテンプレートとして利用するか
・データはどんなデータが来るか
と決めるくらいです。

ここまではいいんですが、例えばフィルタ機能をつけてみるとなった時、どうなるでしょうか。
おそらく以下の様な作業が必要になります。

jQuery

}).done(function(data){
    var filter = $("#filter").val();
    $("#vueadvent").empty();
    data = data.filter(function(val) {
        // 全データに対してフィルタリング
}).error(function(data) {

jQueryの責任範囲的に当然なのですが、全部自分でやる必要があります。
データをフィルタリングしたいならそのデータ全てをフィルタリングする機能を自分で作る必要があります。
それに対して、Vue.jsの場合

Vue.js

        <div id="vueadvent" class="container">
            <data-table v-with="
            data      : gridData,
            columns   : gridColumns,
            filterKey : searchQuery <!-- ☆ -->
            "></data-table>
            <button type="button" class="btn btn-default" v-on="click: reflesh" >更新</button> 
            <input type="text" v-model="searchQuery"><!-- ☆ -->

のように、☆の部分を追加するだけでフィルタリング機能が追加できます。
やはりフロントサイドのJSなので、便利な機能が揃ってますね。

まとめ

jQueryは基本的に全部js側でやるのに対して、
Vue.jsはView側(HTML側)にも責任を負わせる。

というように思いました。(フロントサイドだから当たり前とか言われると辛い)
ピュアなjavascriptに比較的近いjQueryだからこそ、簡単であるけれども、
責任範囲をView側とjavascriptに分けたVue.jsのほうが拡張は楽なんだなぁと思いました。
jQueryだけで何もかもをやろうとするのは、
フレームワークでファットコントローラーな状態に似てるかと思います。
シンプルな処理ならいいのですが、何か複雑なことをjavascriptでやる時は、
うまくライブラリを使いたいなと思います。
色々なものと比較したいなーと思ってるので、次はreact.jsなど試してみようかなと思います。

今日使ったレポジトリはこちらです。



22日分の Vue.js Advent Calendar 2014 - Qiita は偶然にも研究室先輩の tejitak - Qiita
さんです。

Vue.jsでpopup componentを作ってみる | てじーまーのblog