Vue.js+firebaseでJS MVVMフレームワークに入門する(2/2)


#はじめに
(1/2)は[こちら](http://qiita.com/abe00makoto/items/ee7b707f4804c047e11a)

前回firebaseの機能を20行のコード追加で動くようにしてみました。

まとめると

1. 配列への要素追加時にcallback関数が呼ばれるので、
そのcallback関数内でVue.jsのModelへの追加処理を行う
2. 元々の「Vue.jsのModel内の配列へ要素追加を行う」処理だった部分を「firebaseのModelへ要素追加を行う」処理に変更。

上記２点の処理追加or変更を行いました。
図にするとこういうイメージになります。
![model_s.png](https://qiita-image-store.s3.amazonaws.com/0/3844/a957d885-f1d1-21a8-a2d9-a863e5b6a1b8.png "model_s.png")


上図のVue.jsのModelとfirebaseのModelの間の追加処理の部分を実装したイメージとなります。
それ以外はそれぞれのライブラリが吸収してくれるわけですね。便利です。




今回は更に、要素に対する「変更」、「削除」も対応してみます。

配列に対する追加、変更、削除のコールバック関数の対応は以下となります。

#firebaseのModelの変更をVue.jsのModelに反映する

## firebaseのModelを取得

```js:Model
var baseURL = 'https://<<アプリのURL>>.firebaseio.com/',
var Messages   = new Firebase(baseURL + 'messages');

```


## firebaseが配列への追加を検出した際のcallbak

event_type:```child_added ```

```js:追加

Message.on('child_added', function (snapshot) {
    var message = snapshot.val();
    message.id = snapshot.name(); //識別子を取得しvue.jsのModelへ登録しておく。この値で変更時のオブジェクトを検出する
    app.messages.push(message); //vue.jsのmodelへの追加処理
});

```

## firebaseが配列要素変更を検出した際のcallbak

event_type:```child_changed ```

```js:変更
Message.on('child_changed', function (snapshot) {
  var id = snapshot.name();
    app.messages.some(function(message) {
        if (message.id === id) {
            message.body = snapshot.val().body; //変更の反映
            return true;
        }
    });
});

```

## firebaseが配列要素削除を検出した際のcallbak

event_type:```child_removed ```


```js:削除
Messages.on('child_removed', function (snapshot) {
    var id = snapshot.name();
      app.messages.some(function(message) {
          if (message.id === id) {
            app.messages.$remove(message); 
            return true;
          }
      });
  });

```

#Vue.jsのModelの変更をfirebaseのModelに反映する

##追加
```js:追加
Messages.push(this.newMessage);

```
##変更
```js:変更
Messages.child(message.id).child('body').set(message.body);//事前にidを保存しておかないとここで変更ができない
```

##削除
```js:削除
Messages.child(message.id).remove();//事前にidを保存しておかないと削除できない
```


##コード全体

```html:chat_2.html
<html id="app">
  <head>
    <title v-text="title"></title>
    <script src="https://cdn.firebase.com/js/client/1.0.2/firebase.js" charset="utf-8"></script>
    <script src="http://vuejs.org/js/vue.min.js" charset="utf-8"></script>
  </head>
  <body>
    <div v-repeat="message:messages">
        {{$index}}
        <input v-model="message.body" value="{{message.body}}" v-on="keyup:changeMessage(message)">
        from:{{message.from}}
        <button v-on="click:deleteMessage(message)" >x</button>
        <br>
    </div>
    <form id="form" v-on="submit:addMessage">
        from:<br>
        <input v-model="newMessage.from">
        <br>
        message:<br>
        <input v-model="newMessage.body">
        <input type="submit" value="Add Message">
    </form>
  </body>
  <script charset="utf-8">

  //追加箇所
  var baseURL = 'https://<<自分のURL>>.firebaseio.com/',
  Messages   = new Firebase(baseURL + 'messages');

  //追加時
  Messages.on('child_added', function (snapshot) {
      var message = snapshot.val();
      message.id = snapshot.name(); //識別子を取得しvue.jsのModelへ登録しておく。この値で変更時のオブジェクトを検出する
      app.messages.push(message); //vue.jsのmodelへの追加処理
  });

  //変更時
  Messages.on('child_changed', function (snapshot) {
    var id = snapshot.name();
      app.messages.some(function(message) {
          if (message.id === id) {
              message.body = snapshot.val().body; //変更の反映
              return true;
          }
      });
  });

  //削除時
  Messages.on('child_removed', function (snapshot) {
    var id = snapshot.name();
      app.messages.some(function(message) {
          if (message.id === id) {
            app.messages.$remove(message); 
            return true;
          }
      });
  });

  var app = new Vue({
      el: '#app',
      data: {
          title:'Hello myChat',
          messages: [],
          newMessage: {
              from: '',
              body: ''
          },
      },
      methods: {
          addMessage: function(e) {
              e.preventDefault(); //submitをキャンセル

              Messages.push(this.newMessage);
              this.newMessage.body = ''

          },
          changeMessage: function(message) {
            console.log("changeMessage:" + message.body);
            Messages.child(message.id).child('body').set(message.body)
          },
          deleteMessage: function(message) {
            console.log("deleteMessage:" + message.body);
            Messages.child(message.id).remove();
          }

      }
  });

  </script>
</html>

```
# 課題
ここまでは、簡単に作れて感動しましたが、
DB周りが完全公開状態でやりたい放題なのを、なんとかする必要があります。
次回はその辺をまとめてみます。

# おまけ：firebaseのダッシュボードから変更したり、変更を見たりできる。



![dashboard.gif](https://qiita-image-store.s3.amazonaws.com/0/3844/0afd7174-e749-e578-6324-33cf44b83ad3.gif "dashboard.gif")