乐帝当年学习backbone时。最開始是看官网todoMVC的实现。后来了解到requireJS便于管理JS代码。就对官网代码做了requireJS管理。但此时乐帝感觉此时的todoMVC仍然不够简明,为了加深对MVC架构的理解。乐帝对原有appview代码进行了重构,将相关显示模块单独提取出自称view。实现view原子化。乐帝已经将这个项目上传(下载地址)。

   
增加requireJS的文件夹结构:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWluZ3lpbGVkaQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

   这里主要用到templates用于放置view相应的模板。views则相应backbone中view文件。假设说backbone是前端MVC,那么model是对数据建立模型。collection则是对model统一管理,view则起到控制器的作用,用于填充数据到模板,并渲染模板到显示。model、collection起到M作用。view起到C的作用,模板则起到V的作用。

   然后我们看一下todoMVC的效果图:





    从终于效果图。我们能够分析出,要对原有appview中解耦出原子view。就须要推断出哪些是原子view。原子view须要具备两点:

  • 具有动态交互效果
  • 与其它页面部分独立
   当然这里的原子view定义还值得商榷。乐帝依据以上两个原则对view进行了又一次划分。
 
 且看views文件夹结构:


   相应模板文件夹结构:
   须要注意的是,这里appview并没有相应的模板。而是通过设置el: "#todoapp",在index.html文件里,统一对原子view进行管理。

   以下以ToggleAllView类源码为样例,我们分析下,原子view职能的组成:
define([
'jquery',
'underscore',
'backbone',
'text!templates/toggleAll.html'
], function($, _, Backbone, toggleTemplate) {
var ToggleAllView = Backbone.View.extend({
toggleTemplate: _.template(toggleTemplate),
events: {
"click #toggle-all": "toggleAllComplete"
},
initialize: function() {
this.listenTo(this.collection, "all", this.render); //除了todoview与todomodel一一相应
// 其它相关操作都会监听collection
},
render: function() {
this.$el.html(this.toggleTemplate());
var done = this.collection.done().length;
var remaining = this.collection.remaining().length;
this.allCheckbox = this.$("#toggle-all")[0];
this.allCheckbox.checked = !remaining;
return this;
},
toggleAllComplete: function() {
var done = this.allCheckbox.checked;
this.collection.each(function(todo) {
todo.save({
done: done
});
}); //这里通过推断单选框是否选中。改动全部modeldone属性
} });
return ToggleAllView;
});

 上述代码中职能主要有例如以下几种:

  • 设置el或tagname,用于定义在上一层view放置的位置,或包裹的标签
  • 设置相应模板(Template)
  • 定义交互事件,并连带定义交互函数
  • 初始化函数(initialize),一般设置对collection或者model的监听,用于view之间的通信
  • 渲染函数(render),用于渲染数据到模板中。设置其它一些全局函数
   由此可见。原子view将职能划分的非常清楚。这也是前端MVC架构的原因,而不是之前纯脚本时代,代码间高度耦合。牵一发而动全身。
   对于学习backbone,原子view和appview各自代码都不难理解。难于理解或者它精妙之处,在于对事件的监听机制,正是这样的机制,处理了view之间的通信,从而将松散的view拼装成性能优良的整理。

   todoView的监听:
initialize: function() {
this.listenTo(this.model, "change", this.render);
this.listenTo(this.model, "destroy", this.remove); //当模型被删除,视图对应被移除 }

   这里对每一个todoview进行与之绑定的model数据监听。改动,则又一次渲染;销毁。则移除此todoview。

   再看ToggleAllView的监听:
initialize: function() {
this.listenTo(this.collection, "all", this.render); //除了todoview与todomodel一一相应
// 其它相关操作都会监听collection
}

 这个监听更“狠”。仅仅要collection有变动,就会又一次渲染,以达到实时交互的效果。

   那么appview是怎样管理各个子view的呢?
   且看两个appview函数:
 initialize: function() {
// 初始化加入各种视图,新建视图并加入到父视图指定位置
this.footer = this.$el.find('footer');
this.main = $('#main');
this.todoCollection = new todos;
inputview = new InputView({
collection: this.todoCollection
});
$("#todoapp").prepend(inputview.render().el); //加入输入框 var toggleAllview = new ToggleAllView({
collection: this.todoCollection
});
this.main.prepend(toggleAllview.render().el); //取得数据后,再初始化
this.allCheckbox = this.$("#toggle-all")[0]; this.listenTo(this.todoCollection, "add", this.addOne);
this.listenTo(this.todoCollection, "reset", this.addAll);
this.listenTo(this.todoCollection, "all", this.render);
// 须要数据的视图。在获取数据后定义
this.todoCollection.fetch();
// 状态视图
statusview = new StatusView({
collection: this.todoCollection
});
this.footer.append(statusview.render().el); //取得数据后,再初始化
},
render: function() {
// 因为设置了all监听全部collection的操作。故加入一个项就会被渲染一次,这保证了有修改都会得到渲染到页面
var done = this.todoCollection.done().length;
var remaining = this.todoCollection.remaining().length;
this.allCheckbox = this.$("#toggle-all")[0];
if (this.todoCollection.length) {
//渲染时运行显示或隐藏的代码
this.main.show();
this.footer.show();
this.footer.html();
//假设collection为空的话,则清空footer
} else {
this.main.hide();
this.footer.hide();
}
}, // 实现总体显示

   与原子view的差别,在于appview初始化函数除了监听collection变化外。还初始化各个原子view,并加入到指定界面位置,同一时候渲染函数依据逻辑须要。渲染整个页面。
   以上是对整个todoMVC程序的总体性架构分析。详细交互细节可查看乐帝源码。

最新文章

  1. SUSE系统查看各种信息
  2. 怎样录制屏幕并将结果保存为Gif
  3. Windows 10 密钥分享
  4. UVALive3902 Network[贪心 DFS&&BFS]
  5. web代理工具WebScarab
  6. vim基本使用
  7. C# 输出pdf文件流在页面上显示
  8. Android中Activity启动模式详解
  9. SAP第一轮面试之英语群面
  10. 记录break和continue的区别
  11. php的定界符<<<eof的问题
  12. 解决 React-Native mac 运行报错 error Failed to build iOS project. We ran "xcodebuild" command but it exited with error code 65. To debug build logs further, consider building your app with Xcode.app, by ope
  13. 第十五节: EF的CodeFirst模式通过DataAnnotations修改默认协定
  14. Caffe使用新版本CUDA和CuDNN
  15. 利用java8对设计模式的重构
  16. Neo4J 教程
  17. PS学习之合成特效:被风沙侵蚀的动物们
  18. jQuery(六):value值操作
  19. 重命名和重定向RF执行生成的output文件
  20. 015-awk

热门文章

  1. 基于visual Studio2013解决面试题之0506取和为m的可能组合
  2. 基于visual Studio2013解决C语言竞赛题之1057打印加数
  3. spring AOP 是如何一步一步被简化的
  4. Swift - 使用相机拍摄照片
  5. Android中ListView.getCount()与ListView.getChildCount()区别和OnScrollListener()各个参数的区别
  6. 几种快速傅里叶变换(FFT)的C++实现
  7. 安装Linux_[CentOS]系统
  8. hdu 4687 带花树匹配
  9. Cocos2dx中Plugin-X 在android下的整合
  10. 【ASP.NET Web API教程】4.2 路由与动作选择