前端编程提高之旅(六)----backbone实现todoMVC
乐帝当年学习backbone时,最开始是看官网todoMVC的实现,后来了解到requireJS便于管理JS代码,就对官网代码做了requireJS管理。但此时乐帝感觉此时的todoMVC仍然不够简明,为了加深对MVC架构的理解,乐帝对原有appview代码进行了重构,将相关显示模块单独提取出自称view,实现view原子化。乐帝已经将这个项目上传(下载地址)。
加入requireJS的目录结构:
这里主要用到templates用于放置view对应的模板,views则对应backbone中view文件。如果说backbone是前端MVC,那么model是对数据建立模型,collection则是对model统一管理,view则起到控制器的作用,用于填充数据到模板,并渲染模板到显示。model、collection起到M作用,view起到C的作用,模板则起到V的作用。
然后我们看一下todoMVC的效果图:
从最终效果图,我们可以分析出,要对原有appview中解耦出原子view,就需要判断出哪些是原子view,原子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),用于渲染数据到模板中,设置其他一些全局函数
initialize: function() { this.listenTo(this.model, "change", this.render); this.listenTo(this.model, "destroy", this.remove); //当模型被删除,视图相应被移除 }
这里对每个todoview进行与之绑定的model数据监听,修改,则重新渲染;销毁,则移除此todoview。
initialize: function() { this.listenTo(this.collection, "all", this.render); //除了todoview与todomodel一一对应 // 其他相关操作都会监听collection }
这个监听更“狠”,只要collection有变动,就会重新渲染,以达到实时交互的效果。
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(); } }, // 实现整体显示
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。