前端编程提高之旅(四)----backbone初体验

来到新的实习单位,公司的业务模式、组织架构、开发技术、开发规范对于乐帝这样的职场菜鸟来说都是新的,这一周入职的这几天主要在熟悉公司采用的前端架构,前端架构基本包括:backbone、marionette、requirejs。由于乐帝在爱奇艺实习期间,自学了PHP技术,对smarty模板及thinkphp框架有一个了解,接触前端MVC还是有点基础的。

公司有一套专业的前端培训流程清单。这周主要的工作包括:阅读backbone简要文档、读backbone的todoMVC例子、通读backbone官方文档、再读backbone的todoMVC例子、阅读marionette简要介绍、按照todoMVC源码,手写了一遍todoMVC代码、阅读backbone总结文章,总算大体弄清楚了backbone的来龙去脉。

回头来看,对于提升学习效率最高的方法是:阅读简单概念的介绍并配合例子、看一个比较综合的例子对简单概念做吸收、阅读官方文档所有API、敲一遍综合例子做吸收。这样的学习顺序遵循了认识、实践的原则。乐帝基本上按照这样的顺序学习了backbone。下面代码段的注释是乐帝从整体对model、collection、view的理解。

$(function(){
	var Todo = Backbone.Model.extend({
		default:function(){
			return {
				title:"hello ledi",
				order: Todos.nextOrder(),
				done:false
			};
		},
		toggle:function(){
			return this.save(done,!this.get("done"));
		}

	});//构造基本的数据模型及对数据的处理

	TodoList = Backbone.Collection.extend({
		model:Todo,
		localStorage: new Backbone.LocalStorage("todos-backbone"),
		done:function(){
			return this.where({done:true});
		},
		remaining:function(){
			return this.where({done:false});
		},
		nextOrder:function(){
			if(!this.length)
			{
				return 1;
			}
			else{
				return this.last().get("order")+1;
			}
		},
		comparator:"order"
	});//作为数据模型的集合,对模型进行增删查找、排序等管理
	var Todos =new TodoList;
	var TodoView = Backbone.View.extend({
		tagName:"li",
		template: _.template($("#item-template").html()),
		events: {
	      "click .toggle"   : "toggleDone",
	      "dblclick .view"  : "edit",
	      "click a.destroy" : "clear",
	      "keypress .edit"  : "updateOnEnter",
	      "blur .edit"      : "close"
	    },//事件定义,控制交互部分
	    initialize:function(){
	    	this.listenTo(this.model,"change",this.render);
	    	this.listenTo(this.model,"destroy",this.remove);
	    },// 通过监听与model数据实现绑定
	    render:function(){
	    	this.$el.html(this.template(this.model.toJSON()));
	    	this.$el.toggleClass("done", this.model.get("done"));//切换是否有done类,调试查看此类
	    	this.input = this.$(".edit");
	    	return this;
	    },//初始化渲染模板内容,作为显示部分
	    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(e){
	    	if(e.keyCode == 13)
	    	{
	    		this.close();
	    	}
	    },
	    clear:function(){
	    	this.model.destroy();
	    }
	});//todoview与model一一对应,对model数据进行显示及交互操作
    
    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);
	      this.listenTo(Todos, "reset", this.addAll);
	      this.listenTo(Todos, "all", this.render);

	      this.footer = this.$("footer");
	      this.main = $("#main");

	      Todos.fetch();
	    },//监听collection的变化,实现与collection的绑定
	    render:function(){
	    	var done = Todos.done().length;
	    	var remaining = Todos.remaining().length;
	    	if(!Todo.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){
	    	view = new TodoView({model:todo});
	    	this.$("#todo-list").append(view.render().el);
	    },

	    addAll:function(){
	    	Todos.each(this.addOne,this);//这里用到collection和model沟通了
	    },
	    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");
	    	return false;
	    },
	    toggleAllComplete:function(){
	    	var done = this.allCheckbox.checked;
	    	Todos.each(function(todo){todo.save(done,"done");});
	    }
    });//作为全局的view,控制多个todoview显示交互及其他显示模块的交互部分
    var app = new appView;
})//view基本模式:通过初始化及渲染函数进行最初显示,并通过定义事件列表,编写对应执行函数,实现交互

以上例子是乐帝研究的todo例子,并动手敲了一遍,对各个模块功能的理解。model提供数据模型及对数据处理;collection则是model的集合,主要以model为处理对象,对其增删查找、排序等各种操作;view则是传统后端MVC架构中的起Controller功能,主要负责控制显示、交互逻辑。

backbone简要文档对view的论述并没有后来读的文章写得清楚,这里乐帝给出介绍view及模板的典型例子,用于理解view作为MVC核心地位的职能;

  <!-- Templates -->
  <script type="text/template" id="hello-template">  
    <div>  
        <h3 id="hello"><%= message %></h3>

        <button id="toggle">Toggle</button>  
    </div>  
</script> 
<!-- underscore自带模板引擎,通过<%= var %>接收传入的变量  --> 
<script type="text/javascript">
var TestView = Backbone.View.extend({  
 
        events: {  
            "click button#toggle" : "toggle"  
        },  
        initialize: function() {  
            this.template = _.template($("#hello-template").html());  // 设定模板
            this.render();  
        },  
        render: function() {  
            this.$el.html(this.template({message: "hello world!"}));  //  渲染模板  
            return this;  
        },  
        toggle: function() {  
            this.$("#hello").toggle();  
            return this;  
        }    
});  

$(function () {
    var v = new TestView({el: $("#hello")}); 
});
//这个例子中,给出了设置模板、传入参数、渲染页面、添加交互事件的方法,对于理解view功能:显示页面、添加交互,非常有帮助。
//http://blog.csdn.net/raptor/article/details/8566017
</script>

这段代码给出的显示和交互非常简单,麻雀虽小、五脏俱全。能非常清楚的看到view用于显示页面和添加交互所要做的事情。接下来则是model和collection的例子:

var Foo = Backbone.Model.extend({});  
// 或是初始化默认数据  
var Foo = Backbone.Model.extend({  
    defaults: {  
        name: "hello",  
        value: "233"  
    }  
});  
//  或是运行时赋值。  
//  比如这样:  
    var foo = new Foo({name:"world", value:"874"});  
//  或这样:  
    var foo = new Foo;  
    foo.set({name:"world", value:"874"});  

    var FooList = Backbone.Collection.extend({  
    model: Foo  
}); 
    var foos = new FooList;  
     foos.add([{name:"hello", value:"233"},{name:"world", value:"874"}]);  
$(function () {
    $("#hello").text(JSON.stringify(foos.at(0))); ;  
});

 这段代码给出了model及collection基本定义和使用,除此之外还会涉及增删查找、有效性验证、事件绑定等功能。由于都会涉及到后端的交互,这里乐帝涉猎不多,详情可戳我

至于router则是定义路由规则,相对简单。乐帝下一步则是需要在这个基础上使用requirejs组织todoMVC代码以及阅读marionette使用其写一个todoMVC例子,并最终在talentjs上写MVC例子,真正的上手项目。

文章导航