热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

backbonetodo案例分析

todo案例可以到这个地址下载https:github.comjashkenasbackbone添加数据后todo案例不涉及Router,仅有Model、Collec

todo案例可以到这个地址下载 https://github.com/jashkenas/backbone

添加数据后

todo案例不涉及Router,仅有Model、Collection、View的应用,但这个案例对于这三个对象的使用真是已经到了炉火纯青的地步,我看了两天(囧),也只是看懂了表面一层,至于更深一层的思想就太模糊、若有若无了。还需努力啊!

 

todo案例的核心在todos.js文件里,我分析的也是todos.js。

 

首先是数据模型Model

1 var Todo = Backbone.Model.extend({
2 defaults : function() { //看好多人都用function return这种方式,但不知道好处在哪
3 return {
4 title : "empty todo ...",
5 order : Todos.nextOrder(), //要有Todos这个全局变量才行
6 done : false
7 }
8 },
9 //切换状态
10 toggle : function(){
11 this.save({done : !this.get("done")}); //注意:我在这里犯过2次错误,把save写成了set,导致数据保存不上。
12 }, //更新数据要使用 save,不是其他。RESTful风格就是这样。
13 });

这个Model和java中的bean何其相似啊!属性有:title、order、done,方法有 toggle,这个方法也仅仅是更新其中的一个属性而已。

 

然后是集合Collection

1 var TodoList = Backbone.Collection.extend({
2 //model
3 model : Todo, //如java中List集合中的泛型,表面这是一个Todo类型的集合(即集合存储Todo对象)
4
5 //本地存储,操作的数据都存储在localStorage里面,没有后端
6 localStorage : new Backbone.LocalStorage("todos-backbone"),
7 //The app uses a LocalStorage adapter to transparently save all of your todos within your browser, instead of sending them to a server
8
9 //获取状态为 done:true 的Todo对象数组
10 done : function(){
11 return this.where({done : true});
12 },
13 //获取状态为 done:false 的Todo对象数组
14 remaining : function(){
15 return this.where({done : false});
16 },
17
18 //生成下一个Todo对象的编号
19 nextOrder : function(){
20 if(!this.length){ //this.length 获取集合中model的数量
21 return 1;
22 }
23 return this.last().get("order") + 1;
24 },
25
26 comparator : "order" , //按照 order 进行排序
27
28 });

总体来说,这个TodoList集合用来存储Todo对象到localStorage里并为他们编号,同时获取不同状态下的Todo对象。

小结:Model 和 Collection 都是用来存储数据的,里面的操作也都是对数据的操作,不与页面逻辑混合。

 

接下来是TodoView

1 var TodoView = Backbone.View.extend({
2
3 tagName : "li",
4
5 template : _.template($("#item-template").html()), //页面模板,_.template是underScore的函数
6
7 events : { //DOM事件
8 "click .toggle" : "toggleDone",
9 "dblclick .view" : "edit",
10 "click a.destroy" : "clear",
11 "keypress .edit" : "updateOnEnter",
12 "blur .edit" : "close",
13 },
14
15 initialize : function(){ //构造函数
16 //监听Collection的变化并作出反应
17 this.listenTo(this.model, "change", this.render); //model属性改变时会触发该事件
18 this.listenTo(this.model, "destroy", this.remove); //销毁model时,触发该事件。this.remove()移除一个视图(即销毁model的同时移除view)
19 },
20
21 //渲染
22 render : function(){
23 // el是tagName
24 this.$el.html(this.template(this.model.toJSON())); //将model的属性作为参数传入模板生成html代码,同时填充到el元素里
25
26 this.$el.toggleClass("done", this.model.get("done"));//根据model的属性值来判断元素的类
27
28 this.input = this.$(".edit"); //注意这个写法
29
30 return this; //为了链式调用
31 },
32
33 /*** DOM事件处理函数 ***/
34
35 //切换状态
36 toggleDone : function(){
37 this.model.toggle();
38 },
39
40 edit : function(){
41 this.$el.addClass("editing");
42 this.input.focus();
43 },
44
45 close : function(){
46 var value = this.input.val();
47 if(!value){
48 this.clear();
49 }else{
50 this.model.save({title : value});
51 this.$el.removeClass("editing");
52 }
53
54 },
55
56 updateOnEnter : function(){
57 if(e.keyCode === 13){
58 this.close();
59 }
60 },
61
62 clear : function(){
63 this.model.destroy(); //销毁model,触发destroy事件
64 },
65
66 });

每个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

1 var AppView = Backbone.View.extend({
2
3 el : $("#todoapp"),
4
5 statsTemplate : _.template($("#stats-template").html()),
6
7 events : {
8 "keypress #new-todo" : "createOnEnter",
9 "click #clear-completed": "clearCompleted",
10 "click #toggle-all" : "toggleAllComplete",
11 },
12
13 initialize : function(){
14 this.input = this.$("#new-todo");
15 this.allCheckbox = this.$("#toggle-all")[0];
16
17 this.listenTo(Todos, "add", this.addOne); //当有Todo对象添加到Todos集合触发该事件(添加一个model就添加一个view)
18 // this.listenTo(Todos, "reset", this.addAll); //
19 this.listenTo(Todos, "all", this.render); //任何事件的发生都会调用该回调函数this.render
20
21 this.footer = this.$("footer");
22 this.main = this.$("#main");
23
24 Todos.fetch(); //拉取所有的Model对象并保存到Todos集合中,会触发Todos的add事件
25 },
26
27 render : function(){
28 var done = Todos.done().length;
29 var remaining = Todos.remaining().length;
30
31 if(Todos.length){
32 this.main.show();
33 this.footer.show();
34 this.footer.html(this.statsTemplate({done : done, remaining : remaining}));
35 }else{
36 this.main.hide();
37 this.footer.hide();
38 }
39 this.allCheckbox.checked = !remaining;
40 },
41
42 addOne : function(todo){
43 var view = new TodoView({model : todo});
44 view.render();
45 this.$("#todo-list").append(view.el);
46 },
47 /**
48 addAll : function(){
49 //backbone代理了Underscore的一些方法
50 Todos.each(this.addOne, this);
51 },
52 **/
53 createOnEnter : function(e){
54 if(e.keyCode != 13){
55 return;
56 }
57 if(!this.input.val()){
58 return;
59 }
60 Todos.create({title : this.input.val()});
61 this.input.val("");
62 },
63
64 clearCompleted : function(){
65 //_.invoke(Todos.done(), "destroy"); //遍历Todos.done(),每个元素都 todo.destroy();
66
67 _.each(Todos.done(),function(todo){
68 todo.destroy();
69 });
70 return false;
71 },
72
73 toggleAllComplete : function(){
74 var done = this.allCheckbox.checked;
75 Todos.each(function(todo){
76 todo.save({
77 'done' : done,
78 });
79 });
80 },
81
82 });

这个view表示整个页面,比较复杂(自己觉得)。

将它从上到下拆分开来,就变的简单了。

最上面是头,一个标题和一个输入框,输入框有一个DOM事件keypress。

1 <header>
2  <h1>Todosh1>
3  <input id&#61;"new-todo" type&#61;"text" placeholder&#61;"What needs to be done?">
4header>

中间是身体&#xff0c;一个复选框一个label提示信息一个ul列表&#xff0c;复选框有一个DOM事件&#xff0c;而ul列表中li子项则是作为TodoView存在的。

1 <section id&#61;"main">
2 <input id&#61;"toggle-all" type&#61;"checkbox">
3 <label for&#61;"toggle-all">Mark all as completelabel>
4 <ul id&#61;"todo-list">
5 ul>
6 section>

最下是脚&#xff0c;一个div显示信息一个超链接&#xff0c;超链接有一个DOM事件&#xff0c;清除完成的任务。

1 <footer>
2 <a id&#61;"clear-completed">Clear completeda>
3 <div id&#61;"todo-count">div>
4 footer>

 

这样在去看AppView就简单多了。

关键还是内在的思想&#xff0c;可以偶还没看明白&#xff01; >_<

---------------------------------

AppView的数据核心就是 TodoList&#xff0c;TodoList对象的变化要同步到AppView&#xff0c;所有要监听TodoList对象。

 

转:https://www.cnblogs.com/lhat/p/5152237.html



推荐阅读
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • Vue基础一、什么是Vue1.1概念Vue(读音vjuː,类似于view)是一套用于构建用户界面的渐进式JavaScript框架,与其它大型框架不 ... [详细]
  • HyperledgerComposer环境安装1.安装基本软件包**如果使用Linux安装HyperledgerComposer,请注意以下建议:以 ... [详细]
  • vue使用
    关键词: ... [详细]
  • 本文介绍了解决Netty拆包粘包问题的一种方法——使用特殊结束符。在通讯过程中,客户端和服务器协商定义一个特殊的分隔符号,只要没有发送分隔符号,就代表一条数据没有结束。文章还提供了服务端的示例代码。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • NSD cisco高级路由与交换技术2014.8.12
    实验01:DHCP服务的应用实验目标:通过建立DHCP服务,给计算机自动分配地址实验环境:实验步骤:一、配置计算机pc8pc ... [详细]
  • 动态多点××× 单云双HUB
    动态多点是一个高扩展的IPSEC解决方案传统的ipsecS2S有如下劣势1.中心站点配置量大,无论是采用经典ipsec***还是采用greoveripsec多一个分支 ... [详细]
  • Kubernetes(k8s)基础简介
    Kubernetes(k8s)基础简介目录一、Kubernetes概述(一)、Kubernetes是什么(二& ... [详细]
author-avatar
草莓顽子该_589
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有