SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

LINEフロントエンドレンジャーのWeb開発術

お手軽データバインディングライブラリ「Vue.js」を使いこなそう(基礎編)

LINEフロントエンドレンジャーのWeb開発術 第1回

  • X ポスト
  • このエントリーをはてなブックマークに追加

ViewModelの定義

VMインスタンスの生成

 Vue.jsでは、Vueコンストラクタをnewして生成されるVM(ViewModel)インスタンスがコアとなる要素です。まずは、以下の簡単なサンプルを紹介します。

リスト1. VMインスタンスの簡単な例
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <script src="http://vuejs.org/js/vue.min.js"></script>
    </head>
    <body>
        <div id="app">
            <input type="text" v-model="message">
            <div>{{message}}</div>
        </div>
        <script>
            // vmインスタンスの初期化
            var vm = new Vue({
                el: '#app',
                data: {
                    message: ""
                }
            });
        </script>
    </body>
</html>

 上記のHTMLを保存してブラウザで開くと、inputに何か値を入力すると同時にその値が下に表示されます。

図1. 実行例
図1. 実行例

 この例で実装時に開発者が意識して行うステップは以下の3点です。

  1. 入力用のViewの定義:Inputタグ内で、ViewとModelを同期させるためのv-model(ディレクティブ)にmessageプロパティを指定する
  2. 出力用のViewの定義:messageの出力用にHTML内に{{message}}を記述する
  3. Modelの定義:関連付けるDOMエレメントをelに、データバインディング対象のプロパティmessageをdataに指定してVMインスタンスを生成する

 ステップ3のVueコンストラクタをnewしてVMインスタンスを生成すると、内部的にコンパイルと呼ばれる処理が実行され、ViewとModelが双方向にバインディングされます。この双方向バインディングにより、インタラクティブな振る舞いをイベント処理などのコードを一切記述することなく実現できます。

Vue.jsにおけるコンパイル

 Vue.jsではVMインスタンス初期化時にコンパイルと呼ばれる仕組みが実行されます。

 

 コンパイルの前準備として、初期化時にdataで指定したプロパティは列挙可能(enumerable)な各プロパティに対してECMAScript 5のgetter/setterを追加します。コンパイルでは、elで指定されたDOMエレメント自身とその子孫要素を辿り、Vue.jsが付与したgetter/setterを利用してModelとViewの同期処理が可能な状態に変換されます。

 

 本章では、elやdataを代表としたVMインスタンス初期化時のオプションについて解説します(すべての初期化時のオプションについてはOptionsのページを参考にしてください)。

el

 elはVMインスタンスのバインディング対象となるDOMエレメントを指定するオプションです。elにはセレクタによる指定やHTMLノードによる指定ができます(現時点では、セレクタによる複数ノードの指定は対応していません)。

リスト2. VMインスタンス初期化オプションのel
var vm = new Vue({
    el: "#app"
});
// インスタンス生成後には$elでアクセス可能
vm.$el;

 VMインスタンスに関連付けられたDOMエレメント配下でのバインディングには、Mustache記法を使用することができます。

リスト3-1. Mustache記法によるバインディングの例(JavaScript)
var vm = new Vue({
    el: "#app",
    data: {
        text: "通常のテキスト",
        unescapedText: "<div>HTMLを有効化して<br>表示したい時のテキスト</div>",
        onetimeText: "一度だけバインディングされる文字列"
    }
});
リスト3-2. Mustache記法によるバインディングの例(HTML)
<div id="app">
<!-- htmlエスケープされる通常の出力 v-textディレクティブと等価-->
{{text}}
<!-- htmlエスケープされない出力 v-htmlディレクティブと等価 -->
{{{unescapedText}}}
<!-- 一度だけのバインディング -->
{{* onetimeText}}
</div>
Vue.jsにおけるDOM操作

 関連付けられたDOMは自身のmethodsの中でthis.$elとしてアクセスできます(Vue.jsでは基本的にVMインスタンス自身のプロパティおよびメソッドは$接頭辞が付きます)。

 

 ただし、DOM操作のコードを直接記述することは、ViewModelの定義によりDOMを意識させない仕組みを提供するMVVMの思想と反します。DOM操作が必要な場合はカスタムディレクティブを使うと良いでしょう。

data

 dataはMVVMにおけるModelの部分を担うオプションです。dataで指定したオブジェクトは初期化後にvm.$dataとしてアクセス可能です。また、dataオブジェクトはVMインスタンス自身のプロパティとしても同期されます。

リスト4. VMインスタンス初期化オプションのdata
var data = { a: 1 };
var vm = new Vue({
    data: data
});
vm.$data === data; // -> true
// VMインスタンス自身のプロパティとしてアクセスできる
vm.a;  // -> 1

 dataで指定するオブジェクトに対するバインディングのための改変(getter/setterの付与)はVMインスタンス初期化時に行われます。そのため、後から$dataにプロパティを追加した場合、双方向バインディングされない点に注意が必要です。途中からdataにバインディングの対象を追加・削除したい場合は$add, $deleteを使います。

リスト5. $add、$deleteを使用してdataのプロパティを追加・削除する例
// vm.$data.bを追加
vm.$add("b", {value: "hoge"});
// vm.$data.bを削除
vm.$delete("b");
dataの特定プロパティでgetter/setterの付与をスキップしたい場合

 dataに指定した列挙可能(enumerable)なプロパティがバインディングの対象になりますが、「$」か「_」で始まるプロパティに関してはgetter/setterの付与がスキップされます。

methods

 methodsオプションで指定したfunctionはVMインスタンス自身のfunctionとしてミックスインされます。定義したfunctionの実行時のthisのコンテキストはVMインスタンス自身になります。

リスト6. VMインスタンス初期化オプションのmethods
var vm = new Vue({
    data: { a: 1 },
    methods: {
        plus: function () {
            // thisのcontextはvmインスタンス自身になる
            this.a++;
        }
    }
});
// vmインスタンスから直接呼ぶことができる
vm.plus();
vm.a; // 2

 上記の例はvmインスタンスから直接呼び出す例です。他にも後述のディレクティブの項で紹介するv-onを用いてmethodsで定義したfunctionを呼び出すこともできます。

computed

 computedオプションはカスタムのgetter/setterを定義することができる仕組みです。指定したプロパティはVMインスタンスにミックスインされます。また、指定したgetter/setterのthisのコンテキストはVMインスタンス自身になります。

リスト7. VMインスタンス初期化オプションのComputed
var vm = new Vue({
    data: { a: 1 },
    computed: {
        // function1つのみの定義の場合はgetterとして動作する
        aDouble: function () {
            return this.a * 2;
        },
        // getterとsetter両方を指定
        aPlus: {
            get: function () {
                return this.a + 1;
            },
            set: function (v) {
                this.a = v - 1;
            }
        }
    }
});
vm.aPlus;   // getterが呼ばれる -> 2
vm.aPlus = 3; // setterが呼ばれる
vm.a;       // -> 2
vm.aDouble; // -> 4

ライフサイクル

 VMインスタンスのライフサイクルの各メソッドを生成時のオプションとして指定できます(v0.11より前のバージョンではcreatedやreadyなどタイミングがv0.11と異なるので注意が必要です)。

表1. ライフサイクルオプション
ライフサイクル 説明
created DOMのコンパイル以外(dataの監視の仕組みなど)がすべて終わったタイミングで呼ばれる
beforeCompile コンパイルが始まる直前に呼ばれる
compiled コンパイルが終わり双方向バインディングが準備された状態で呼ばれる($elがDOMに挿入されていることは保証されていない)
ready コンパイルが終わり初めて$elがDOMに挿入された時に呼ばれる
attached ディレクティブや$appendToなどにより$elがDOMに挿入された時に呼ばれる
detached ディレクティブや$removeなどにより$elがDOMから取り除かれた時に呼ばれる
beforeDestroy $destroyが呼ばれる直前に呼ばれる(vmインスタンスが正しく動作する)
destroyed $destroyが呼ばれ、バインディングなどがすべてはずされ、子孫要素のvmインスタンスも破棄された時点で呼ばれる
リスト8. VMインスタンスのライフサイクルcreatedとreadyの例
var vm = new Vue({
    el: "#app",
    data: { a: 1 },
    created: function(){
        this.a++; // DOMに挿入される前の処理
        this.$el; // -> null, this.$elがまだセットされていない
    },
    ready: function(){
        this.$el.parentNode; // DOMに挿入された後なので、$elや親ノードにアクセスできる
    }
});

その他のVMインスタンス初期化時のオプション

 これまで紹介した代表的なVMインスタンス初期化時のオプション以外にも、例えば、watchなど多数のオプションが存在します。watchは指定したプロパティに対して変更監視のコールバックを登録するオプションです。

リスト9. VMインスタンス初期化オプションのWatch
var vm = new Vue({
    data: { a: 1 },
    watch: {
        'a': function (newVal, oldVal) {
             console.log('new: ' + newVal + ', oldVal: ' + oldVal);
        }
    }
});
vm.a = 2 // -> new: 2, old: 1

 初期化時のオプションと同様に、$接頭辞から始まるVMインスタンス自身のプロパティやメソッドもさまざまなものが提供されています。例えば、上記で紹介したオプションwatchの内部ではインスタンスメソッドである$watchが使用されています。本稿では解説しませんが、興味のある方はインスタンスメソッドのページをご参照ください。

次のページ
ディレクティブ

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
LINEフロントエンドレンジャーのWeb開発術連載記事一覧

もっと読む

この記事の著者

手島 拓也(LINE株式会社)(テジマ タクヤ)

日本IBM研究所にて検索・テキスト解析ソフトウェア製品の開発に従事した後、現在はLINEにてWebフロントエンド開発を担当。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/8363 2015/01/14 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング