初探
backbone采用MVC模式,本身提供了模型、控制器和视图从而我们应用程序的骨架便形成。
Backbone.js 唯一重度依赖 Underscore.js. 对于 RESTful , history 的支持依赖于 Backbone.Router , DOM 处理依赖于Backbone.View , json2.js, 和 jQuery ( > 1.7) 或 Zepto 之一.
中文文档
http://www.css88.com/doc/backbone/
英文文档
http://documentcloud.github.io/backbone/
充斥着大量Ajax交互的富应用页面,类应用程序和单页界面,数据操作和展示全部由客户端完成。
Backbone的执行顺序:
路由(Backbone.Router)-> 模型(Backbone.Model)-> 视图(Backbone.View)
1 App.Controllers.Routes = Backbone.Router.extend({ 2 routes: { 3 "!/hello" : "hello",//使用#!/hello驱动路由 这里会去执行下面hello这个函数 4 }, 5 hello : function(){ 6 //新建一个模型,模型向后端请求更新内容成功后根据模型渲染新页面 7 var helloModel = new App.Models.Hello; //调用模板 8 helloModel.fetch({ 9 success: function(model){ //成功拿到数据,调用视图渲染页面 10 var helloView = new App.Views.Hello({model: model}); 11 helloView.trigger('change'); //绑定change事件 12 } 13 }); 14 } 15 });
1 App.Models.Hello = Backbone.Model.extend({ 2 url: function() { 3 return '/index/test'; // 获得数据的后台接口地址。 4 }, 5 initialize: function() { 6 this.set({'message':'hello world'}); // 前端定义一个message字段,name字段由接口提供。 7 } 8 });
1 App.Views.Hello = Backbone.View.extend({ 2 el: "body", //在哪里显示 3 template: $("#hello-container-template").html(), //获取模板 模板是用Mustache 4 initialize: function(options){ 5 this.options = options; 6 this.bind('change', this.render); 7 this.model = this.options.model; 8 }, 9 render: function(){ // render方法,目标只有两个:填充this.el,返回this以便链式操作。 10 $(this.el).html(Mustache.to_html(this.template,this.model.toJSON())); 11 return this; 12 } 13 });
var App = { Models: {}, Views: {}, Controllers: {}, Collections: {}, initialize: function() { new App.Controllers.Routes(); Backbone.history.start() // 要驱动所有的Backbone程序,Backbone.history.start()是必须的。 } }; // 调用 App.initialize();
•模型属性
定义模型、实例化
1 var User = Backbone.Model.extend({ 2 initialize: function (name) { 3 this.set({name: name}); 4 } 5 }); 6 var user = new User('啦啦啦'); // 实例化 7 8 // 属性 9 user.set({ age: 999 }); 10 user.get('age'); //999 11 user.attributes;//{name: '啦啦啦',age:999}
user.arributes是一个对象字面量,我们不会直接操作他,因为我们使用get/set方法可以进行我们的验证流程。
使用validate方法来校验一个实例属性,默认情况没有任何验证:
1 var User = Backbone.Model.extend({ 2 validate: function (attr) { 3 if (!attr.name || attr.name.length < 3) { 4 return 'too short'; 5 } 6 if(!attr.age || !(/^\d{1,3}$/).test(attr.age)){ 7 return 'ghost?'; 8 } 9 } 10 }); 11 // 不合法可以返回错误字符串或者Error对象,校验失败get/set方法就会触发error事件: 12 13 //统一的错误处理 14 user.bind('error', function (model, error) { 15 16 }); 17 18 //给特定集合添加一个错误处理程序 19 user.set({ age: 999}, { error: function (model, error) { } });
•视图
backbone的视图并不是模板,而是一些控制类,视图代表一个UI逻辑块,负责一个简单的DOM内容
一个视图提供一个由 el
属性定义的 HTML 元素。该属性可以是由 tagName
、className
和 id
属性相组合而构成的,或者是通过其本身的 el
值形成的
1 App.Views.Team = Backbone.View.extend({ 2 initialize : function() { 3 _.bindAll(this, 'render', 'close'); // bindAll保证了所有给定的函数总是在指定的上下文中被调用 4 this.model.bind("change", this.render, this); // Render() 方法绑定到模型变更事件 5 this.model.bind('delete', this.remove); // 模型销毁需要视图绑定delete事件 6 } 7 className : '.team-element', 8 tagName : 'div', 9 model : new App.Models.Team 10 template: _.template($('#tmpt').html()), // 模板 11 render: function () { 12 $(this.el).html(this.template(this.model.toJSON())); 13 return this; 14 }, 15 close: function () { }, 16 remove: function () { $(this.el).remove() }, 17 18 // 事件属性 19 events: { 20 'change input[type=checkbox]': 'toggleDone', 21 'click .destroy': 'clear' 22 }, 23 toggoleDone: function () { }, 24 clear; function () {} 25 26 });
•路由
控制器是一些路由和函数组成,当导航到这些路由时那些函数便调用
1 App.Routers.Main = Backbone.Router.extend({ 2 3 // Hash maps for routes 4 routes : { 5 "" : "index", 6 "/teams" : "getTeams", 7 "/teams/:country" : "getTeamsCountry", 8 "/teams/:country/:name : "getTeam" 9 "*error" : "fourOfour" 10 }, 11 12 // http://www.example.com 触发 13 index: function(){ 14 // Homepage 15 }, 16 17 // http://www.example.com/#/teams 触发 18 getTeams: function() { 19 // List all teams 20 }, 21 22 // http://www.example.com/#/teams/country1 触发 getTeamsCountry() 传递 country1 作为参数 23 getTeamsCountry: function(country) { 24 // Get list of teams for specific country 25 }, 26 27 // http://www.example.com/#/teams/country1/team1 触发 getTeamCountry() 传递 country1 和 team1 作为参数 28 getTeam: function(country, name) { 29 // Get the teams for a specific country and with a specific name 30 }, 31 32 // http://www.example.com/#/something 触发 fourOfour() 以作 * (星号)使用。 33 fourOfour: function(error) { 34 // 404 page 35 } 36 }); 37 38 // 要启动 Backbone,先实例化页面加载的路由器,并通过指令 Backbone.history.start() 方法监视散列片段中的任何变更 39 40 $(function(){ 41 var router = new App.Routers.Main(); 42 Backbone.history.start({pushState : true}); 43 })
•与服务器同步
模型发生变化(保存),backbone就会使用ajax与服务器通讯(Backbone.sync),成功便更新客户端模型。
定义url,并且在服务器端处理rest形式请求,backbone会处理:
1 var User = Backbone.Model.extend({ 2 url: '/users' 3 });
增删改查:
create => post /collection read => get /collection[/id] update => put /collection/id delete => delete /collection/id
//例如,我们要创建一个User实例,backbone会发送一个post请求道/uesrs,更新一个user实例,会发送至/users/id节点
使用save(attr, option)函数将模型保存至服务器,可以随意传递一个由属性和请求项组成的hash对象,若是模型有id,假设该模型在服务器上以存在,存在就是put请求,不然就post请求添加数据
1 var user = new User(); 2 user.set({ name: '叶小钗' }); 3 user.save(null, { 4 success: function () { 5 //保存成功 6 } 7 }); 8 // 所有save都是异步的,通过success或者failure来监听ajax回调,我们一般与jquery合用了。
•自定义行为
在backbone视图读取或者保存模型到服务器时都会调用backbone.sync方法,
覆盖该方法来改变其默认行为(存入xml、本地存储):
1 //所有待完成的项都保存至本地存储命名空间“todos”中 2 Toto.prototype.localStorage = new Store('todos'); 3 //重写backbone.sync 4 Backbone.sync = function (method, model, options) { 5 var resp, store = model.localStorage || model.collection.localStorage; 6 switch (method) { 7 case 'read': resp = model.id ? store.find(model) : store.findAll(); break; 8 case 'create': resp = store.create(model); break; 9 case 'update': resp = store.update(model); break; 10 case 'delete': resp = store.destroy(model); break; 11 } 12 if (resp) { 13 options.success(resp); 14 } else { 15 options.error('not find'); 16 } 17 } // 注: 每个模型或者集合只能覆盖各自的sync函数
扩展阅读
7条建议
http://ourjs.com/detail/5353191719fe673f1700000e