Backbone.jsの基本
細かいことはサンプルコードで、ということで……
backbone.js v1.0.0
function l(s) {console.log(s)}; function a(s) {alert(s)}; l('*****start*****'); l('*****Backbone.Model*****'); var Todo = Backbone.Model.extend({ defaults: { title: '' ,completed: false } ,initialize: function() { l('*** model initialize***'); this.on('change', function(){l('model has changed');}); this.on('change:title', function(){l('title has changed');}); this.on('invalid', function(){l(this.validationError)}); } ,validate: function(attrs) { if(!_.isBoolean(attrs.completed)) { return 'completedはブーリャンでお願いしますね!'; } } }); var todo = new Todo({title: 'sample'}); l(JSON.stringify(todo)); l(todo.get('title')); l(todo.attributes.title); l(todo.hasChanged());//false l(todo.hasChanged('title'));//false l(todo.hasChanged('completed'));//false todo.set('title', 'changed title'); l(todo.get('title')); l(todo.hasChanged());//true l(todo.hasChanged('title'));//true l(todo.hasChanged('completed'));//false todo.set('completed', 'hoge'); todo.save();// invalid l('*****Backbone.View*****'); var TodoView = Backbone.View.extend({ id: 'sample_view' ,className: 'sample_class1 sample_class2' ,tagName: 'li' ,template: _.template('example') ,events: { 'dblclick label': 'edit' ,'keypress .edit': 'updateOnEnter' ,'blur .edit': 'close' } ,render: function() { this.$el.html(this.template(this.model.toJSON())); this.input = this.$('.edit'); return this; } ,edit: function(){} ,updateOnEnter: function(){} ,close: function(){} }); var todoView = new TodoView(); l(todoView.el); l(todoView.$el); var button = $('<button></button>'); todoView.el = button; l(todoView.el);//jQueryオブジェクトになっちゃってる l(todoView.$el);//前から変わってない todoView.setElement(button); l(todoView.el);//期待通り l(todoView.$el);//期待通り todoView.el = '<input/>'; l(todoView.el);//期待通り l(todoView.$el);//前から変わってない l('*****Backbone.Collection*****'); (function(){ var collection = new Backbone.Collection; collection.add([{id:1, name:'dog'},{id:2, name:'cat'}]); l(JSON.stringify(collection)); collection.add([{id:1, name:'dogdog'}], {merge:true}); l(JSON.stringify(collection));//id:1のモデルのnameがマージされてdogdogになる l(collection.get(1));//上でマージしたやつ l(collection.get(1).idAttribute);//id })(); var TodoList = Backbone.Collection.extend({ model:Todo }); var todoList = new TodoList(); todoList.on('add', function(model){l(model.cid + ' added to collection');}); todoList.on('remove', function(model){l(model.cid + ' removed from collection');}); todoList.on('change', function(model){l(model.cid + ' changed in collection');}); todoList.on('change:title', function(model){l(model.cid + ' title changed in collection');}); todoList.on('reset', function(models,options){ l('collection reset'); l(models); _.each(options.previousModels, function(m){ l(' ' + m.cid + ' removed'); }); _.each(models.models, function(m){//models.modelsってなんだ…… l(' ' + m.cid + ' added'); }); }); var todo = new Todo({title: 'sample'}); l(todo.id);//undefined l(todo.cid);//c1とか l(todo.idAttribute);//id todoList.add([todo]); l(JSON.stringify(todoList)); //l(list.get(0).get('title'));//idがないからidでgetはできない l(todoList.get(todo.cid).get('title'));//sample todoList.add([{id: 0, title: 'sample'}]); //別にnew Todo()しなくても属性値だけでaddできちゃう l(todoList.get(0).get('completed'));//Todoとしてaddされているのでちゃんとfalseと出力される //一旦Collectionにaddしたならmodel単体で操作してもCollection側のイベントハンドラは有効 var temp = todoList.get(0); temp.set('title', 'タイトル変えてみるわ');//Todo,TodoList両方でchangeイベントがハンドリングされる todoList.remove(0); todoList.reset([{id: 0, title: 'dog'}, {title: 'cat'}]);//完全に中身を作り直す todoList.set([{id:0, title: 'dogdog'}, {title: 'mouse'}]);//add,remove,changeを駆使する todoList.reset();//resetイベントのみ発生
Backbone.Model
RubyのActiveRecordみたいにhasChangedで変更有無を調べられるのはよかった。setter(model.set(attr, val)
)でセットしないと変更されたと見なされないのも同じ。
バリデーションはイベントだけが提供されていて、Railsのsexy validationみたいなのはない。
Backbone.View
HTML要素1つに紐付くっぽい。そのdom elementを一から作るなら、
var v = Backbone.View.extend({ id: 'sample_view' ,className: 'sample_class1 sample_class2' ,tagName: 'li' });
と言った調子で表現できる。
既に存在する要素に対しては
var v = Backbone.View.extend({ el: '#sample_view' });
var v = Backbone.View.extend({}); v.setElement($('<button></button>'));
といった調子。newしたあとにv.el
に直接代入するのはよくないっぽいので上記2つ以外はやらない方がたぶんいい。
setElement()
で要素を設定したらel
と$el
両方が自動セットされる。