backbone-todo案例分析
todo案例可以到这个地址下载 https://github.com/jashkenas/backbone
添加数据后
todo案例不涉及Router,仅有Model、Collection、View的应用,但这个案例对于这三个对象的使用真是已经到了炉火纯青的地步,我看了两天(囧),也只是看懂了表面一层,至于更深一层的思想就太模糊、若有若无了。还需努力啊!
todo案例的核心在todos.js文件里,我分析的也是todos.js。
首先是数据模型Model
var Todo = Backbone.Model.extend({
defaults : function() { //看好多人都用function return这种方式,但不知道好处在哪
return {
title : "empty todo ...",
order : Todos.nextOrder(), //要有Todos这个全局变量才行
done : false
}
},
//切换状态
toggle : function(){
this.save({done : !this.get("done")}); //注意:我在这里犯过2次错误,把save写成了set,导致数据保存不上。
}, //更新数据要使用 save,不是其他。RESTful风格就是这样。
});
这个Model和java中的bean何其相似啊!属性有:title、order、done,方法有 toggle,这个方法也仅仅是更新其中的一个属性而已。
然后是集合Collection
var TodoList = Backbone.Collection.extend({
//model
model : Todo, //如java中List集合中的泛型,表面这是一个Todo类型的集合(即集合存储Todo对象) //本地存储,操作的数据都存储在localStorage里面,没有后端
localStorage : new Backbone.LocalStorage("todos-backbone"),
//The app uses a LocalStorage adapter to transparently save all of your todos within your browser, instead of sending them to a server //获取状态为 done:true 的Todo对象数组
done : function(){
return this.where({done : true});
},
//获取状态为 done:false 的Todo对象数组
remaining : function(){
return this.where({done : false});
}, //生成下一个Todo对象的编号
nextOrder : function(){
if(!this.length){ //this.length 获取集合中model的数量
return 1;
}
return this.last().get("order") + 1;
}, comparator : "order" , //按照 order 进行排序 });
总体来说,这个TodoList集合用来存储Todo对象到localStorage里并为他们编号,同时获取不同状态下的Todo对象。
小结:Model 和 Collection 都是用来存储数据的,里面的操作也都是对数据的操作,不与页面逻辑混合。
接下来是TodoView
1 var TodoView = Backbone.View.extend({ tagName : "li", template : _.template($("#item-template").html()), //页面模板,_.template是underScore的函数 events : { //DOM事件
"click .toggle" : "toggleDone",
"dblclick .view" : "edit",
"click a.destroy" : "clear",
"keypress .edit" : "updateOnEnter",
"blur .edit" : "close",
}, initialize : function(){ //构造函数
//监听Collection的变化并作出反应
this.listenTo(this.model, "change", this.render); //model属性改变时会触发该事件
this.listenTo(this.model, "destroy", this.remove); //销毁model时,触发该事件。this.remove()移除一个视图(即销毁model的同时移除view)
}, //渲染
render : function(){
// el是tagName
this.$el.html(this.template(this.model.toJSON())); //将model的属性作为参数传入模板生成html代码,同时填充到el元素里 this.$el.toggleClass("done", this.model.get("done"));//根据model的属性值来判断元素的类 this.input = this.$(".edit"); //注意这个写法 return this; //为了链式调用
}, /*** DOM事件处理函数 ***/ //切换状态
toggleDone : function(){
this.model.toggle();
}, edit : function(){
this.$el.addClass("editing");
this.input.focus();
}, close : function(){
var value = this.input.val();
if(!value){
this.clear();
}else{
this.model.save({title : value});
this.$el.removeClass("editing");
} }, updateOnEnter : function(){
if(e.keyCode === 13){
this.close();
}
}, clear : function(){
this.model.destroy(); //销毁model,触发destroy事件
}, });
每个View视图都有一个DOM元素,这个DOM元素就是el,这个view里所有关于页面的操作都必须在el下(注意,在view操作el的父元素或同级元素都将无效),如果没有指定el,那么el将从tagName、className、id创建,如果也没有,那么el就是一个空的div。
TodoView视图表示的就是ul中的一个li,如
写view的思路:
1、 el,这是一个view的根元素
2、template,这是view的模板,该模板将在render插入到el元素中
3、render,渲染页面,负责将model的数据显示在html模板中
4、DOM事件,想象该view哪些地方需要和用户进行交互,然后在events中绑定事件
5、完成DOM事件处理函数
6、观察哪些操作造成了哪些数据的变化,为这些数据绑定事件,当数据变化时更新数据并再次渲染页面。
比如上面的TodoView,el是li,模板渲染需要Todo数据,在这个li里,要有
- 单击checkbox,更新model数据
- 单击li后面的X号,删除model
- 双击li,变成编辑状态
- 回车或者焦点离开更新model数据
我自己的感觉,前5个步骤都比较简单,就是第6步用起来有些生涩。不过多几次就好了!
最后是AppView
var AppView = Backbone.View.extend({ el : $("#todoapp"), statsTemplate : _.template($("#stats-template").html()), events : {
"keypress #new-todo" : "createOnEnter",
"click #clear-completed": "clearCompleted",
"click #toggle-all" : "toggleAllComplete",
}, initialize : function(){
this.input = this.$("#new-todo");
this.allCheckbox = this.$("#toggle-all")[0]; this.listenTo(Todos, "add", this.addOne); //当有Todo对象添加到Todos集合触发该事件(添加一个model就添加一个view)
// this.listenTo(Todos, "reset", this.addAll); //
this.listenTo(Todos, "all", this.render); //任何事件的发生都会调用该回调函数this.render this.footer = this.$("footer");
this.main = this.$("#main"); Todos.fetch(); //拉取所有的Model对象并保存到Todos集合中,会触发Todos的add事件
}, render : function(){
var done = Todos.done().length;
var remaining = Todos.remaining().length; if(Todos.length){
this.main.show();
this.footer.show();
this.footer.html(this.statsTemplate({done : done, remaining : remaining}));
}else{
this.main.hide();
this.footer.hide();
}
this.allCheckbox.checked = !remaining;
}, addOne : function(todo){
var view = new TodoView({model : todo});
view.render();
this.$("#todo-list").append(view.el);
},
/**
addAll : function(){
//backbone代理了Underscore的一些方法
Todos.each(this.addOne, this);
},
**/
createOnEnter : function(e){
if(e.keyCode != 13){
return;
}
if(!this.input.val()){
return;
}
Todos.create({title : this.input.val()});
this.input.val("");
}, clearCompleted : function(){
//_.invoke(Todos.done(), "destroy"); //遍历Todos.done(),每个元素都 todo.destroy(); _.each(Todos.done(),function(todo){
todo.destroy();
});
return false;
}, toggleAllComplete : function(){
var done = this.allCheckbox.checked;
Todos.each(function(todo){
todo.save({
'done' : done,
});
});
}, });
这个view表示整个页面,比较复杂(自己觉得)。
将它从上到下拆分开来,就变的简单了。
最上面是头,一个标题和一个输入框,输入框有一个DOM事件keypress。
<header>
2 <h1>Todos</h1>
3 <input id="new-todo" type="text" placeholder="What needs to be done?">
</header>
中间是身体,一个复选框一个label提示信息一个ul列表,复选框有一个DOM事件,而ul列表中li子项则是作为TodoView存在的。
<section id="main">
<input id="toggle-all" type="checkbox">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">
</ul>
</section>
最下是脚,一个div显示信息一个超链接,超链接有一个DOM事件,清除完成的任务。
<footer>
<a id="clear-completed">Clear completed</a>
<div id="todo-count"></div>
</footer>
这样在去看AppView就简单多了。
关键还是内在的思想,可以偶还没看明白! >_<
---------------------------------
AppView的数据核心就是 TodoList,TodoList对象的变化要同步到AppView,所有要监听TodoList对象。
backbone-todo案例分析的更多相关文章
- Java设计模式—门面模式(带案例分析)
1.门面模式的定义: 门面模式(Facade Pattern)也叫做外观模式,是一种比较常用的封装模式,其定义如下: 要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行.门面模式 ...
- Java多态案例分析
一.多态的定义 同一事物,在不同时刻体现出不同状态. 例如:水在不同状态可能是:气态.液态.固态. 二.多态前提和体现 1.有继承关系 2.有方法重写 3.有父类引用指向子类对象 三.编译运行原理 1 ...
- mybatis入门案例分析
mybatis入门案例分析 一.设计模式分析 public class MybatisTest { public static void main(String[] args) throws Exce ...
- 098 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 02 编写并测试Subject类
098 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 02 编写并测试Subject类 本文知识点:编写并测试Subject类 说明: ...
- 099 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 03 编写并测试Student类
099 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 03 编写并测试Student类 本文知识点:编写并测试Subject类 说明: ...
- 101 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联——方案二
101 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联--方案二 本文知识点:通过方法实现学生类与 ...
- 18.jvm调优工具及案例分析
目标: Jmap.Jstack.Jinfo详解 JvisualVm调优工具实战 JVM内存或CPU飙高如何定位 JState命令预估JVM运行情况 系统频繁Full GC导致系统卡顿实战调优 内存泄漏 ...
- ENode框架Conference案例分析系列之 - 文章索引
ENode框架Conference案例分析系列之 - 业务简介 ENode框架Conference案例分析系列之 - 上下文划分和领域建模 ENode框架Conference案例分析系列之 - 架构设 ...
- Backbone源码分析(三)
Backbone源码分析(一) Backbone源码分析(二) Backbone中主要的业务逻辑位于Model和Collection,上一篇介绍了Backbone中的Model,这篇文章中将主要探讨C ...
随机推荐
- BLUEZ测试报告
测试小分队介绍: 马辰,李孟,罗凡 测试任务分类 帮助类 战斗类 道具类 敌军类 英雄类 地图类 AboutScene.h AchieveLayers.h GameLoading.h GameOver ...
- Codeforces Round #360 (Div. 1) D. Dividing Kingdom II 并查集求奇偶元环
D. Dividing Kingdom II Long time ago, there was a great kingdom and it was being ruled by The Grea ...
- vim跳到文件头和文末结尾
gg : 跳转到文件头 Shift+g : 跳转到文件末尾
- 简单几何(线段覆盖) POJ 3347 Kadj Squares
题目传送门 题意:告诉每个矩形的边长,它们是紧贴着的,问从上往下看,有几个还能看到. 分析:用网上猥琐的方法,将边长看成左端点到中心的距离,这样可以避免精度问题.然后先求出每个矩形的左右端点,然后如果 ...
- Sky数[HDU2097]
Sky数 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- cocos2d 定时器
//获取当前系统的语言 LanguageType language=CCApplication::sharedApplication()->getCurrentLanguage(); //每一帧 ...
- BZOJ1172 : [Balkan2007]Dream
$\gcd(ab,k)=\gcd(\gcd(a,k)\times \gcd(b,k),k)$ 设$f[i][j]$表示前$i$行,与$k$的$\gcd$为$j$的方案数,$h[i]$表示当前行选一个或 ...
- ios 适应屏幕
标准做法:auto layout 其中:也可以用代码判断 1.如果不是hardcode的话,又怎么会不兼容呢.. 2.如果你全写320*480也是兼容吗 3.写320嘛的就是hardcode啊. ...
- (转)Linq学习笔记
写在前面 最近在看Linq,在博客园看到这篇文章,写的通俗易懂,转来和大家一起做个分享.原文地址http://www.cnblogs.com/goscan/archive/2011/05/05/Lin ...
- TYVJ P1002 谁拿了最多奖学金 Label:模拟 水
背景 NOIP2005复赛提高组第一题 描述 某校的惯例是在每学期的期末考试之后发放奖学金.发放的奖学金共有五种,获取的条件各自不同:1) 院士奖学金,每人8000元,期末平均成绩高于80分( ...