最近在读Addy Osmani的Developing Backbone.js Applications,读到了第一个栗子todos,必然要合上书自己再实现一遍。
书上用了一个backbone.localStorage插件,backbone还在初学,不想理会插件,先用window.localStorage直接原始的处理,之后在研究这个插件。
Model部分
todo.js
var app = app || {}; app.Todo = Backbone.Model.extend({ defaults: { content: ‘‘, completed: false }, //toggle完成状态 toggle: function(bool) { if(bool === true) { this.set(‘completed‘, true); } else if(bool === false) { this.set(‘completed‘, false); } else { this.set(‘completed‘, !this.get(‘completed‘)); } } });
Collection部分
todos.js
var app = app || {}; (function () { var TodoList = Backbone.Collection.extend({ model: app.Todo, //window.localStorage storage: window.localStorage || null, initialize: function() { this.on(‘all‘, this.updateStorage); }, remaining: function () { return this.filter(function (todo) { return todo.get(‘completed‘) === false; }); }, completed: function () { return this.where({completed: true}); }, //页面初始化时加载,用reset方法一次放入所有model,会触发collection的reset事件 readStorage: function() { if (!this.storage) return; var todo_json = this.storage.getItem(‘todo‘); if (todo_json) this.reset(JSON.parse(todo_json)); }, //任何变动就更新storage的数据 //JSON.stringify,被转换对象如果有toJSON()方法,则转换toJSON()的返回值而不是当前对象了,Model的toJSON()返回它的attriubutes属性,Collection的toJSON(),返回包含所有内部model的attributes对象的数组 updateStorage: function() { if (!this.storage) return; var todo_json = JSON.stringify(this); this.storage.setItem(‘todo‘, todo_json); } }); app.todos = new TodoList(); })();
视图部分
item-view.js, 控制ul里每一项li
var app = app || {}; app.TodoView = Backbone.View.extend({ tagName: ‘li‘, template: _.template($(‘#item-tpl‘).html()), //没有用keypress,非字符键不会触发keypress,捕捉不到ESC键。keydown返回键盘的代码,keypress是把keydown返回值翻译为ASCII码 events: { ‘dblclick label‘: ‘edit‘, ‘click .toggle‘: ‘toggle‘, ‘blur .edit‘: ‘close‘, ‘keydown .edit‘: ‘updateOnEnter‘, ‘click .clear‘: ‘clear‘ }, initialize: function() { this.listenTo(this.model, ‘change‘, this.render); this.listenTo(this.model, ‘destroy‘, this.remove); }, render: function() { this.$el.html(this.template(this.model.toJSON())); this.$el.toggleClass(‘completed‘, this.model.get(‘completed‘)); this.$edit = this.$(‘.edit‘); return this; }, edit: function() { this.$el.addClass(‘editing‘); this.$edit.focus(); this.$edit.select(); }, close: function() { var value = this.$edit.val(); if(value.trim()) { this.model.set(‘content‘, value); } else { this.clear(); } this.$el.removeClass(‘editing‘); }, updateOnEnter: function(e) { if(e.which === ENTER_KEY) { this.close(); } else if(e.which === ESC_KEY) { this.$el.removeClass(‘editing‘); this.$edit.val(this.model.get(‘content‘)); } }, clear: function() { this.model.destroy(); }, toggle: function() { this.model.toggle(); } });
app-view.js
var app = app || {}; app.AppView = Backbone.View.extend({ el: ‘#todo-app‘, template: _.template($(‘#footer-tpl‘).html()), events: { ‘keydown #new-todo‘: ‘createOnEnter‘, ‘click #toggle-all‘: ‘toggleAll‘, ‘click .clear-completed‘: ‘clearCompleted‘ }, initialize: function () { this.$list = this.$(‘#todo-list‘); this.$new = this.$(‘#new-todo‘); this.allCheckbox = this.$(‘#toggle-all‘)[0]; this.$main = this.$(‘#todo-main‘); this.$footer = this.$(‘#todo-footer‘); this.listenTo(app.todos, ‘add‘, this.addOne); this.listenTo(app.todos, ‘all‘, this.render); this.listenTo(app.todos, ‘reset‘, this.addAll); app.todos.readStorage(); }, render: function () { var remaining = app.todos.remaining().length, completed = app.todos.completed().length; this.$footer.html(this.template({ remaining: remaining, completed: completed })); this.$clearCompleted = this.$(‘.clear-completed‘); this.allCheckbox.checked = !remaining; if (app.todos.length) { this.$main.show(); this.$footer.show(); } else { this.$main.hide(); this.$footer.hide(); } return this; }, newAttributes: function () { return { content: this.$new.val(), completed: false } }, addOne: function (todo) { var view = new app.TodoView({model: todo}); this.$list.append(view.render().el); }, addAll: function(todos) { todos.each(function(todo) { this.addOne(todo); }, this); }, createOnEnter: function (e) { if (e.which === ENTER_KEY && this.$new.val().trim() != "") { app.todos.add(this.newAttributes()); this.$new.val(‘‘); } }, clearCompleted: function () { app.todos.completed().forEach(function (todo) { todo.destroy(); }); }, toggleAll: function () { var value = this.allCheckbox.checked; app.todos.forEach(function (todo) { todo.toggle(value); }, this); } });
最后,index.js
var ENTER_KEY = 13, ESC_KEY = 27, app = app || {}; $(function() { new app.AppView(); });
时间: 2024-10-04 19:44:19