vue.jsとmilkcocoaを使ってアカウント機能付きメモアプリを作ってみた

今日は[milkcocoa](https://mlkcca.com)を使って、プライベートなメモアプリを作ってみましょう。

## 何を作るのか

簡単な自分だけのメモを残せるアプリを作ります。自分だけしかメモを見られないようにするために、新規登録、ログイン機能を作ります。また今回はフレームワークとして、[vue.js](http://vuejs.org/)を利用しています。[ソースコード](https://github.com/milk-cocoa/login)も公開しているので、参考にしてください。

デモ：[メモアプリ](http://login.mlkcca-app.com/)
ソースコード全体：[Github](https://github.com/milk-cocoa/login)

![スクリーンショット 2014-09-20 22.12.45.png](https://qiita-image-store.s3.amazonaws.com/0/54243/f6c762bf-b379-fe88-3976-17aea7b6d7d0.png)


## 最初に

まずはMilkCocoaに接続するために、以下のコードを書きます。

```js

var milkcocoa = new MilkCocoa("https://[your-app-id].mlkcca.com");

```

Vueオブジェクトを作成します。


```js

var app = new Vue({
    el: '#content',
    data: {
        currentView: null
    }
});
```

Vueでアプリケーションを作成する際の参考には、以下も参照ください。

* はじめようVue.js
http://qiita.com/kitfactory/items/9c9b9312ace03e731b33
* Building Larger Apps
http://vuejs.org/guide/application.html


## 新規登録

アカウントの新規登録画面用のVueコンポーネントを作成します。

![スクリーンショット 2014-09-20 1.20.57.png](https://qiita-image-store.s3.amazonaws.com/0/54243/f9892fe2-89f2-65a8-9722-4a73566268d4.png)

新規登録にはaddAccount関数を使います。addAccountが成功した場合、app.currentViewをloginに切り替えることで、画面遷移しています。

```js

Vue.component('register', {
    template: "#register-template",
    data : {
            email : "",
            password : "",
            confirm : ""
    },
    methods : {
        register : function() {
            var self = this;
            if(this.password != this.confirm) return;
            milkcocoa.addAccount(this.email, this.password, {}, function(err, user) {
                if(err == MilkCocoa.Error.AddAccount.FormatError) {
                    self.message = "フォーマットエラー";
                }else if(err == MilkCocoa.Error.AddAccount.AlreadyExist) {
                    self.message = "Emailアドレスが既に使われています。";
                }else{
                    app.currentView = "login";
                }
            });
        },
        goto_login_view : function() {
            app.currentView = "login";
        }
    }
});
```

HTMLのテンプレートは省略してます。


## ログイン

新規登録画面ができたので、ログイン画面を作りましょう。

![スクリーンショット 2014-09-20 1.21.54.png](https://qiita-image-store.s3.amazonaws.com/0/54243/3396b125-b281-fc17-2261-12a173a13e9e.png)

ログイン画面用のVueコンポーネントを作成します。milkcocoa.login関数を利用してログインを実現します。コールバックのerrパラメータで、表示するエラーを変えています。今回は、どのエラーにも合致しない場合に、ブラウザ自体を更新します。

```js

Vue.component('login', {
    template: "#login-template",
    data : {
            email : "",
            password : "",
            message : ""
    },
    methods : {
        login : function() {
            var self = this;
            milkcocoa.login(this.email, this.password, function(err, user) {
                if(err == MilkCocoa.Error.Login.FormatError) {
                    self.message = "フォーマットエラー";
                }else if(err == MilkCocoa.Error.Login.LoginError) {
                    self.message = "Emailかパスワードが違います。";
                }else if(err == MilkCocoa.Error.Login.EmailNotVerificated) {
                    self.message = "メールを確認してください。";
                }else{
                    location.reload();
                }
            });
        },
        goto_reg_view : function() {
            app.currentView = "register";
        }
    }
});
```

ブラウザが更新された際に、getCurrentUser関数を使って、現在ログイン中のユーザを取得します。この処理はlogin.jsの最下部にあります。これによりログイン済みである場合と、そうでない場合での振り分けができます。

```js

milkcocoa.getCurrentUser(function(err, user) {
  if(user) {
    memoDataStore = getMemoDataStore(user);
    current_email = user.email;
    app.currentView = "memo";
  }else{
    app.currentView = "login";
  }
});
```

## メモを投稿

これでログイン画面ができたので、メモを投稿できるようにしましょう。
まずuserオブジェクトを用いて、ユーザ用のデータストアを作成するgetMemoDataStore関数を作ります。

```js

function getMemoDataStore(user) {
  return milkcocoa.dataStore("memo").child(user.id);
}
```

メモ投稿画面用のVueコンポーネントを作成します。memo_filterではmemoデータをビューに渡す前処理を書いています。メモの投稿処理や取得処理は下に詳しく書いています。

```js

Vue.component('memo', {
    template: "#memo-template",
    data : {
        memos : [],
        new_memo : ""
    },
    filters: {
        memo_filter : function(memos) {
            return memos.map(function(memo, index) {
                return {
                    content : escapeHTML(memo.content),
                    color1 : index % 2 == 0,
                    color2 : index % 2 == 1
                }
            });
        }
    },
    ready : function() {
        this.fetch();
        this.email = current_email;
    },
    methods : {
        add_memo : function() {
          //メモ投稿処理
        },
        fetch : function() {
          //メモを取得する処理
        },
        logout : function() {
            milkcocoa.logout(function() {
                location.reload();
            });
        }
    }
});
```


**メモ投稿処理**

プッシュする前に"<"と">"をescapeしてます。

```js

//メモデータストアにメモ内容を追加
memoDataStore.push({
  content : escapeHTML(this.new_memo)
});
//投稿用のテキストエリアをクリア
this.new_memo = "";
```

**メモ取得処理**

表示する前にも"<"と">"をescapeしてます。
JavaScriptのunshift関数を用いることで、一番上に最新の投稿を表示します。

```js

var self = this;
//メモデータストアのpushイベントの監視
memoDataStore.on("push", function(e) {
  self.memos.unshift({
    content : escapeHTML(e.value.content)
  });
});
//メモデータストアから最新データを５件取得
memoDataStore.query().sort('desc').limit(5).done(function(memos) {
  self.memos = memos;
});
```


## セキュリティルール

最後にセキュリティルールで、ユーザごとに作成したデータストアにセキュリティルールを適用します。これにより自分以外のデータストアを操作することはできなくなります。milkcocoaの管理画面のセキュリティルールタブで、以下のセキュリティルールを設定してください。

```css

memo/[userid]/* {
  permit : all;
  rule : account.id == userid;
}
```

管理画面のセキュリティルール

![スクリーンショット 2014-09-20 7.09.42.png](https://qiita-image-store.s3.amazonaws.com/0/54243/7dcd1a7f-5fa1-3c00-b981-8451f0828f33.png)


これで完成です。従来までのメモアプリの作り方と比較してどうでしょうか。milkcocoaはハッカソンや日曜プログラミングにも良いですが、フレームワークと組み合わせれば複雑なアプリにも耐えられることが分かったと思います。シリコンバレーではBaaSをバックエンドに選択するプロジェクトも増加傾向にあるので、検討してみてはいかがでしょうか。

milkcocoa : https://mlkcca.com