Upload
ryuma-tsukano
View
2.704
Download
4
Embed Size (px)
DESCRIPTION
jscafeのBackboneの1回目。Parse(クラウドサービス)を使って、簡単なtodoアプリを作って、BackboneのMV*がどんな物か?見て行くという内容。
Citation preview
introduction toBackbone.js with Parse.com
Ryuma Tsukano
jsCafe7(2013/5/19)
×
趣旨
BackboneのMV*とは何か?
実際のsourceを作って全体を把握するのが目的
※単にアプリ作っても面白くないのでParseというBaaS使う
目次
● BackboneのMV*構成● Parse.com● tutorial● ソース振り返り
サーバー側
Backboneの基本構成
HTTP Request Router
View CollectionModels
Data Source(ex:DB/API)
model更新
modelイベント
syncs
Template
html描写
DOMイベント
BackboneのMV*
● model○ データとそれに関するビジネスロジックを扱う。
● collection○ 複数のデータの集合。ソートや集計等を扱う。
● view○ ロジックがあり再利用可能なUIの小片。
● router○ urlと関数の関連付けを行う。
● template○ htmlの小片。
これから
よくあるToDOアプリを作ります
そして、
単に書くだけでは面白くないので....
Parse使う
Parseとは
BaaS(Backend as a Service):クラウドサービス
● 要するに以下をやってくれる○ Backend側プログラム
■ Restに沿って独自APIを事前に準備● ※今迄rails等で書いていた物がParse側で準備されている
○ storage■ 非公式だがcouchDBという噂が。
● ※今迄mySQL等構築していた物がParse側で準備されてる
○ 今は、色々出来る事が増えてるみたい■ 認証?/analytics?/push通信?■ 最近hostingも始まった。
つまり
開発者はClient側だけ作れば良い○ Web : front側だけ○ スマホ : native側だけ
● 色んなシチュエーションで使えそう○ 開発者いないけどDBにデータ入れたい○ 個人開発スマホアプリで気軽にdata保存したい○ とりあえずモック作りたい○ 勿論、実際の製品に使ってる例も沢山有り
イメージ
注意:構成は非公開なのでimage
Rest API
NoSQLっぽい何か
Web/AppServerClient
CRUD操作等
json
事例
● 山のようにある○ スマホアプリで多く使われている○ 日本でも事例ちらほら。
ちなみに
Facebookに買収されたらしい(2013/4月末)● とっても未来のあるサービス
Client
沢山ある。
● iOS版● Android版● .NET版● javascript版 ★これからこれを使う★
○ Backbone.jsベース(古いBackboneのfork)■ 少しだけ記述が違う
● Backbone.Model => Parse.Object● Backbone.Collection => Parse.Collection● Backbone.View => Parse.View
● 基本的にBackboneをParseにすれば良いが、Modelだけ
Objectになってる点、注意。
sample手順
1. ユーザー登録 ○ sign upでメアド登録
2. Dashboardでアプリ作成(create New App)3. QuickStartGuide をclick
○ ①javascript選択○ ②new project選択○ ③Blank〜Parse SDK(zip)をdownload
4. 解凍後index.htmlのParse.initializeを置換5. index.htmlをbrowser確認
○ We’ve also just created...=>成功
これでコピペ
index.html見てみる
● 以下を保存○ TestObject(Excelシート/tableみたいな物)○ foo : bar (列と値/カラムと値みたいな物)
Parse.initialize("APPLICATION_ID", "JAVASCRIPT_KEY"); var TestObject = Parse.Object.extend("TestObject"); var testObject = new TestObject(); testObject.save({foo: "bar"}, { success: function(object) { $(".success").show(); }, error: function(model, error) { $(".error").show(); } });
index.htmlのhead見てみる
● parse-x.x.x.min.jsを呼んでる○ Backboneをwrapしたjsファイル○ storageのsync先がParseになってる
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript" src="http://www.parsecdn.com/js/parse-1.2.12.min.js"></script>
ついでに
dev tool見てみると
※送信時に
● api.parse.comと通信● jsonが返ってきてる
データオブジェクト
Parse.comのdashboardでdataを確認できる
ToDoApps
今日作るToDoアプリの構成
● サーバー/ストレージ○ ToDoのCRUD
■ Parseに記録
● クライアント○ 表示/Event
■ Backbone.jsを使う● 但し本物のBackbone.jsではなく● Parse-x-x-x.min.jsでwrapされたもの(少しだけ仕様違う)
tutorial
1. HTML準備2. Model作成3. Collection作成4. View作成● 先程のsampleのindex.htmlをベースに
○ ※実際はそれぞれfileを分けるが今日は1fileで
HTML準備
10行付近jQuery前:underscore.jsを追加
20行付近div#main:中身を削除。以下上書。
<script type="text/javascript" src="http://underscorejs.org/underscore.js"></script>
<div id="main"> <form id="todo-form"> <input type="text" id="title"/> <input type="submit"/> </form> <div id="error"></div> <div id="todo-list"> <ul></ul> </div> </div> <span class='help' style="display:none;">text入れて送信するだけね<a href='#'>戻る</a></span>
フォーム
表示領域
バリデーション
キーを指定
● scriptタグ内はParse.initialize以外削除○ ※APP_ID/JS_KEYは先程のをそのまま使って
<script type="text/javascript"> Parse.initialize("APP_ID", "JS_KEY"); // ここに以降、追加していきます
</script>
Model作成
● Parse.Object(=Backbone.model)
○ 特にschema定義不要(schemaless)○ validation:値の検証
■ 今回:空白をcheck!
var Todo = Parse.Object.extend({ className:"Todo", validate: function(attrs){ if(_.isEmpty(attrs.title)){ return "please write text!"; } }});
Collection作成
● Parse.Collection(=Backbone.Collection)
○ Todoモデルを束ねる○ ソート等書く
var TodoList = Parse.Collection.extend({ model: Todo });
今回のView構成
● 結果表示○ ①TodoView : Todoの1つ(liの中)○ ②TodoListView : 複数のTodoの一覧(ul)
● フォーム○ ③TodoFormView : 送信をcheck
● 全体○ ④AppView : 初期処理
■ 各View準備■ Parseからdata読取
①②
③
View作成(①:1つのtodo)
● Parse.View(=Backbone.View)
○ tagName: このViewを囲うtag○ template : htmlのテンプレート(後述)○ render : 描写処理を書く関数○ el : 対象要素
var TodoView = Parse.View.extend({ tagName: "li", template: _.template($('#todo-template').html()), render: function(){ this.$el.html(this.template(this.model.toJSON())); return this; }});
View作成 : template
● templateは、scriptタグで外に出せる(後述)○ 先程のtemplateから呼び出している○ jsp等と同じように変数を埋め込める(title)
● このtemplateを①のViewが描写している
<script type="text/template" id="todo-template"> <strong>[TODO]</strong> <span><%- title %></span> </script>
View作成(②:複数のtodo)
● Parse.View(Backbone.View.extend)○ el : 対象要素(どこに描写するか指定)○ initialize : 初期処理
■ collectionにadd■ =>render
○ render:描写処理■ collectionループ■ 自分の要素内に■ ①のViewを描写
var TodoListView = Parse.View.extend({ el: "#todo-list > ul", initialize: function(){ this.collection.on("add", this.render, this); }, render: function() { this.$el.html(""); this.collection.each(function(todo) { var todoView = new TodoView({model:todo}); this.$el.append(todoView.render().el); },this); return this; } });
View作成(③:フォーム)
● Parse.View(Backbone.View.extend)○ events : イベント
■ submitあったら、■ createTodo関数を実行
○ createTodo : オリジナル関数■ inputタグからTodoを作成■ error時は#errorにmessage
● 先程のvalidationここで表示
■ validationで問題なければ● Todoを保存● 成功したらcollectionに追加
var TodoFormView = Parse.View.extend({ el: "#todo-form", events: { "submit": "createTodo" }, createTodo: function(e) { e.preventDefault(); var todo = new Todo(); todo.on('error', function(model, error) {$('#error').html(error);}); todo.set({title : $('#title').val()}) if(todo.isValid()) { $('#error').html(''); todo.save(null, { success: _.bind(function(todo) { this.collection.add(todo); $('#title').val(''); }, this) }); }; } });
View作成(④:アプリ全体)
● 初期処理○ Parse.Query(class名).findでParseから一覧取得○ 各View(②list③form)を初期化して準備
■ ②listは、Parseのdataを表示 var AppView = Parse.View.extend({ initialize: function(){ new Parse.Query("Todo").find({ success: _.bind(function(list){ var todoList = new TodoList(list); var todoFormView = new TodoFormView({collection: todoList}); this.todoListView = new TodoListView({collection: todoList}); this.render(); }, this) }); }, render: function(){ this.todoListView.render(); return this; } });
Router作成
● Parse.Router(=Backbone.Router)
○ initialize■ ④初期View準備
○ routes:URLと関数を紐付け■ URL:#help(アンカー)■ help関数実行
● help用のhtml表示
○ raisのconfig/routes.rb的な物○ history.start
■ routeのdispatchを開始
var TodoRouter = Parse.Router.extend({ initialize: function(){ var appView = new AppView(); }, routes: { "help" : "help", "" : "show" }, help : function() { $('#main').hide(); $("span.help").show(); }, show : function() { $("span.help").hide(); $('#main').show(); } }); var todoRouter = new TodoRouter; Parse.history.start();
ソースを見ると
● 全体○ データ(M)と表示処理(V)が分かれている
■ データに対してのロジックなのか、画面描写に関して
の処理なのか明確に○ Viewも1画面の中でUIの構成要素毎に分かれている
■ DOMのEventがごちゃごちゃしない。
少し長いソースになったけど、
何やってるかは分かり易いソースになった。
Modelについて
● 特にスキーマを定義しない● 1つと複数とをmodel/collectionで分ける
○ 例)Twitterで言うと■ userがmodel■ follower/followがcollection
● 実際Backboneを使う時はurlを指定してRESTのルールに従ってデータを送受信
Viewについて
普通のバックエンドのViewと少し違う
● BackboneのView=表示用のlogicを含む。○ rails等backendのView = erb/jsp等templateだが
● Viewのソースを見ると○ DOMとEventの紐付きが分かり易い○ 画面描写何してるかはrender見れば何となく分かる
○ よくある文字リテラルによるhtml作成でなく、template使うのでどんな画面になるかimageし易い
router
urlのアンカーに対応して関数実行
● 別画面、tab、popup等用途色々ありそう● single page application用途
#help#
サーバー側
基本構成をもう一度
HTTP Request Router
View CollectionModels
Data Source(ex:DB/API)
model更新
modelイベント
syncs
Template
html描写
DOMイベント
おしまい