Backbone model collection (jscafe 8)

28
BackboneModel Collection ryuma tsukano jsCafe8

description

BackboneのModelとCollectionのまとめ。Backboneの全3回の2回目の内容。

Transcript of Backbone model collection (jscafe 8)

Page 1: Backbone model collection (jscafe 8)

BackboneのModel と Collectionryuma tsukano

jsCafe8

Page 2: Backbone model collection (jscafe 8)

目次● MV*の振り返り● localstorage● Model

○ extend○ メソッド○ 初期化/初期値○ 属性操作○ CRUD○ id/cid/id attribute○ validate○ event

● Collection○ modelとの関連○ ソート○ 基本操作○ underscoreから委譲されたメソッド○ chain○ CRUD○ event

Page 3: Backbone model collection (jscafe 8)

BackboneのMV*BackboneのMV* (公式page+補足)● Model

○ ビジネスロジックに必要なデータの集まり○ rails等のmodelと同じイメージ。

● Collection○ クライアント側のモデルのグループ。○ ソートやフィルターや集計ロジックを書く。

● Router○ URLと関数を繋ぐ○ railsのroutes.rb + controller action

● View○ ロジック込みで再利用できるUIの小片。○ 玉に、(常ではないが)modelと関連付く

● Template(client side)○ HTMLの固まり○ railsの .html.erb view

Page 4: Backbone model collection (jscafe 8)

今日はlocalstorageを使う

html5のlocalstorage自分自身のPC内にdata(Key&Value)を蓄積する仕組み

Page 5: Backbone model collection (jscafe 8)

Backbone.localstoragebackboneでlocalstorage使う為のplugin有りhttps://github.com/jeromegn/Backbone.localStorage

■HTML

<script type="text/javascript" src="backbone.js"></script>

<script type="text/javascript" src="backbone.localStorage.js"></script>

■JS

SomeCollection = Backbone.Collection.extend({

localStorage: new Backbone.LocalStorage("SomeCollection")

});

Page 6: Backbone model collection (jscafe 8)

また手を動かしましょう

html作るの面倒臭いので、既にlocalstorage+Backbone有る環境でchrome devtoolsのconsloleで試そう

=>Backboneのtodo適宜ソース試してみてね。

Page 7: Backbone model collection (jscafe 8)

model

Page 8: Backbone model collection (jscafe 8)

Backboneのmodel基本文法

//クラスのようなもの ※以降クラスと略

var MyModel = Backbone.Model;

//インスタンスのようなもの ※以降インスタンスと略

var model = new MyModel;

※var model = new MyModel({ name : "test" })のように初期値を指定できる。

Page 9: Backbone model collection (jscafe 8)

extendextend関数に独自のメソッドを入れて独自のクラスを作る● Backboneのextend inspired by google closure

○ = underscoreの_.extend■ = JS継承パターン、プロパティのコピー

var MyModel = Backbone.Model.extend({ 独自の処理 });

var model = new MyModel;

Page 10: Backbone model collection (jscafe 8)

メソッド● インスタンスメソッド:インスタンスで使える● スタティックメソッド:クラスで使える

● インスタンス変数、スタティック変数も同じ

var MyModel = Backbone.Model.extend(

{インスタンスメソッド : function () { ... } } ,

{スタティックメソッド : function () { ... } }

);

MyModel.スタティックメソッド

var my_model = new MyModel;

my_model.インスタンスメソッド

Page 11: Backbone model collection (jscafe 8)

初期化● インスタンス時のnew Model(attr, opt)● =>クラスの

○ initialize内関数()

var Human = Backbone.Model.extend({ initialize : function () { console.log('initialize now! '); }});

var human = new Human;// => initialize now !

Page 12: Backbone model collection (jscafe 8)

初期値default : デフォルト値を入れる● newの引数内の初期値に無い項目を埋めてくれる● ※objectを入れる場合、関数にしないと他のinstanceにも影響

●●●● initialize と defaultの違い★

○ initialize : parameter自体を元に処理書ける(動的なデフォルト値)○ default : default値=>与えたparamで上書き(静的なデフォルト値)

var Human = new Backbone.Model.extend({ defaults : { "name" : "taro", "age" : "20" }});

var defaultman = new Human;defaultman.attributes // =>{"name": "taro", "age":20}

var yamada = new Human({"name":"yamada"}) yamada.attributes // => {"name":"yamada", age:20}

var hanako = new Human({"name":"hanako", "age":18})hanako.attributes // {"name":"hanako", "age":18}

Page 13: Backbone model collection (jscafe 8)

属性● get/set:取得/格納● has:確認● attributes:全体の値の取得

var human = new Backbone.Model;

human.set('name', 'Yamada');human.set('age', 18);// ちなみに、human.set({"name":"Yamada", "age":18})とも書ける

human.get('age'); // 18human.has('age'); // true

human.attributes; // {"age": 18}

Page 14: Backbone model collection (jscafe 8)

CRUD:

● 作成更新:save(=>jqueryの$.ajax通信)○ isNew(※後述)で作成/更新(post/put)分けてる ※Rest詳細は次回

● 読み込み:fetch● 削除:destroy

var Human = Backbone.Model.extend({localStorage : new Backbone.LocalStorage("ACollection")//この書き方間違ってます。本来 collectionで使うべき。あくまで説明用に使ってます。

})

var human = new Human;human.set({"name":"taro"});human.save(); // この2行をhuman.save({"name":"taro"})でもいける

var another = new Human({"id": human.id});another.fetch();another.attributes; // => name:taro

Page 15: Backbone model collection (jscafe 8)

id● id : データのID

○ isNew()は、このidの有無で判別(id無ければisNew=true)● cid : モデル作成時にbackboneが発番。

○ 保存してないのでid無いが、Viewに存在する場合扱い易くする為● idAttribute : サーバーから提示されたIDがどれか示す。

○ デフォルトはid。例えば、mongodbなら_idにする。

var Human = Backbone.Model;var human = new Human({"name":"taro"});

console.log("id : " + human.id);console.log("cid : " + human.cid); // c1console.log("isNew : " + human.isNew() ); // true idが無いから

human.set("id":123)console.log("isNew : " + human.isNew() ); // false idが有るから

Page 16: Backbone model collection (jscafe 8)

validationmodel.validate(attr, opt)=値のチェック

戻り値● 正常:戻り値なし● 異常:戻り値あり(エラーobj/msg等)

validateするtiming● save前に必ず● set時に{validate:true}付けた時に

○ ※Parseはsave内でvalidate無い?

エラー時の動作● saveしない

○ setでvalidateした時はsetしない● invalidイベントの引き金を引く● validationErrorプロパティが着く

複数ある時はerr msg等1つのobjにまとめて最後にreturnしないと全部出ない

var Human = Backbone.Model.extend({ validate : function (attrs, options) { if (!attrs.age) { return "you need write age"; } }})

var noage = new Human;noage.set({"name": "yamada"}, {"validate":"true"});

console.log(noage)// => validateErrorプロパティがある

Page 17: Backbone model collection (jscafe 8)

model間の参照関係

1:n等の関連付けの方法が一番気になりますよね。=>Backboneには、この仕組み無い。

選択肢● 1の方にnの内容も埋める

○ メリット:扱い楽チン○ デメリット:階層が深くなると管理が大変

● RDBみたいに、nの方にid入れる○ メリット:再利用性高い○ デメリット:取得処理が冗長/煩雑になる可能性

使うstorageによっても制約条件が異なるのでcase by case(ex. mongodbはjoinが無い)

plugin有るみたい● backbone-relational● 他にも幾つか類似plugin有り

Page 18: Backbone model collection (jscafe 8)

ModelのEvent※Event自体の詳細は次の回にお任せ

元々Modelに以下のイベントが仕込まれている● add : collectionに追加された時● remove : ● change : [attr] 値が変わった時● destroy : ● request : ● sync : ● error : ● invalid : validateして失敗した時

赤=よく使う

var Human = Backbone.Model.extend({ initialize : function () { this.on('change', this.show_msg, this); }, show_msg : function() { console.log('Human is now changing'); }});

var human = new Human({"age":31});human.set("age",18);

Page 19: Backbone model collection (jscafe 8)

collection

Page 20: Backbone model collection (jscafe 8)

Backboneのcollectionコレクション=複数のデータが入る基本的な使い方はmodelと一緒● extendする● クラスとインスタンスがある

var MyCollection = Backbone.Collection.extend({ ... }) // この中に独自処理書く

collection = new MyCollection([

{ id:1, "name":"a"},

{ id:2, "name":"b"}

])

collection.models; // {id:1, "name":"a", id:2, "name":"b"}

Page 21: Backbone model collection (jscafe 8)

基本操作● 追加 : add● 取得 : get(id or cid) / where({key:value}) / at(index)● 全部取得:models● 削除:remove(target)

var People = Backbone.Collection.extend();var japanese = new People;

japanese.add({"id":1, "name":"taro"});japanese.add({"id":2, "name":"hanako"});

japanese.get(1); // {"id":1, "name":"taro"}japanese.where({"name":"taro"}); // {"id":1, "name":"taro"}japanese.models(); // {"id":1, "name":"taro"}, {"id":2, "name":"hanako"}

var yamada_taro = japanese.at(0);japanese.remove(yamada_taro);

Page 22: Backbone model collection (jscafe 8)

modelとの関係付け

modelに指定

var Person = Backbone.Model;

var People = Backbone.Collection.extend({ model : Person});

var japanese = new People;japanese.add(new Person({"name":"yamada"}));japanese.add([ new Person({"name":"tanaka"}), new Person({"name":"yoshida"})]);

japanese.models

Page 23: Backbone model collection (jscafe 8)

ソート3通り書き方あり● model.get(カラム)● 1 / -1を返して並び替え● カラムを指定

var People = Backbone.Collection.extend({ // 3通りの書き方あり(全部一緒) comparator : function(model){

return model.get("id"); } comparator : function(a,b){

return a.get('id') < b.get('id') ? -1 : // aがbより前の時-1 a.get('id') > b.get('id') ? 1 : 0 // bがaより前の時1

} comparator : 'id'});

Page 24: Backbone model collection (jscafe 8)

underscoreから委譲された関数● forEach : よくあるイテレータ● map/pluck/find等役立つ関数いっぱいある

○ rubyと同じ感覚で操作できる

var People = Backbone.Collection;

japanese = new People([ {"name" : "yamada"}, {"name" : "tanaka"}]);

japanese.forEach(function(model){ console.log(model.get('name'));})

Page 25: Backbone model collection (jscafe 8)

chainメソッド

.chain. ... .value() : underscoreからのメソッドチェーン(無いとArray)

var People = Backbone.Collection;var people = new People([ {"name":"yamada", "age":31, blood : "A"}, {"name":"tanaka" , "age": 18, blood : "B"}, {"name":"yoshida" , "age" : 25, blood : "A"}])// =======================================var a_person = people.chain() .filter(function(person) { return person.get('blood') == "A"; // A型のデータを抽出 }) .max(function(person){ return person.get("age"); // ageが最大のものを抽出 }) .value(); // 2つの条件を満たしたyamadaさんがとれるはず

console.log(a_person.attributes);

Page 26: Backbone model collection (jscafe 8)

CRUD● 追加:create● 取得:fetch

○ ※ちなみに、syncは次回!Restと一緒に見ます!

var People = Backbone.Collection.extend({ localStorage : new Backbone.LocalStorage("PeopleCollection")})var people = new People;people.create({"name":"taro"});people.create({"name":"hanako"});

var another = new People;people.fetch(); // {"name": "taro"},{"name": "hanako"}

console.log(people.models)

Page 27: Backbone model collection (jscafe 8)

collectionのevent● add :● remove : ● reset :● sort :● destroy :

さっきのmodelのイベントと一緒。使い方含め、次のEvent参考。

Page 28: Backbone model collection (jscafe 8)

model/collectionは終わり

お次はview/event