Backbone model collection (jscafe 8)
-
Upload
ryuma-tsukano -
Category
Technology
-
view
1.610 -
download
1
description
Transcript of Backbone model collection (jscafe 8)
BackboneのModel と Collectionryuma tsukano
jsCafe8
目次● MV*の振り返り● localstorage● Model
○ extend○ メソッド○ 初期化/初期値○ 属性操作○ CRUD○ id/cid/id attribute○ validate○ event
● Collection○ modelとの関連○ ソート○ 基本操作○ underscoreから委譲されたメソッド○ chain○ CRUD○ event
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
今日はlocalstorageを使う
html5のlocalstorage自分自身のPC内にdata(Key&Value)を蓄積する仕組み
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")
});
また手を動かしましょう
html作るの面倒臭いので、既にlocalstorage+Backbone有る環境でchrome devtoolsのconsloleで試そう
=>Backboneのtodo適宜ソース試してみてね。
model
Backboneのmodel基本文法
//クラスのようなもの ※以降クラスと略
var MyModel = Backbone.Model;
//インスタンスのようなもの ※以降インスタンスと略
var model = new MyModel;
※var model = new MyModel({ name : "test" })のように初期値を指定できる。
extendextend関数に独自のメソッドを入れて独自のクラスを作る● Backboneのextend inspired by google closure
○ = underscoreの_.extend■ = JS継承パターン、プロパティのコピー
var MyModel = Backbone.Model.extend({ 独自の処理 });
var model = new MyModel;
メソッド● インスタンスメソッド:インスタンスで使える● スタティックメソッド:クラスで使える
● インスタンス変数、スタティック変数も同じ
var MyModel = Backbone.Model.extend(
{インスタンスメソッド : function () { ... } } ,
{スタティックメソッド : function () { ... } }
);
MyModel.スタティックメソッド
var my_model = new MyModel;
my_model.インスタンスメソッド
初期化● インスタンス時のnew Model(attr, opt)● =>クラスの
○ initialize内関数()
var Human = Backbone.Model.extend({ initialize : function () { console.log('initialize now! '); }});
var human = new Human;// => initialize now !
初期値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}
属性● 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}
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
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が有るから
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プロパティがある
model間の参照関係
1:n等の関連付けの方法が一番気になりますよね。=>Backboneには、この仕組み無い。
選択肢● 1の方にnの内容も埋める
○ メリット:扱い楽チン○ デメリット:階層が深くなると管理が大変
● RDBみたいに、nの方にid入れる○ メリット:再利用性高い○ デメリット:取得処理が冗長/煩雑になる可能性
使うstorageによっても制約条件が異なるのでcase by case(ex. mongodbはjoinが無い)
plugin有るみたい● backbone-relational● 他にも幾つか類似plugin有り
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);
collection
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"}
基本操作● 追加 : 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);
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
ソート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'});
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'));})
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);
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)
collectionのevent● add :● remove : ● reset :● sort :● destroy :
さっきのmodelのイベントと一緒。使い方含め、次のEvent参考。
model/collectionは終わり
お次はview/event