《BackboneJS框架的技巧及模式》(3)

简介: 四、页面部分刷新 当第一次使用Backbone.js开发应用时,典型的视图结构是像这样的: [javascript] view plaincopyprint? var View = Backbone.

四、页面部分刷新

当第一次使用Backbone.js开发应用时,典型的视图结构是像这样的:


[javascript]   view plain copy print ?
  1. var View = Backbone.View.extend({  
  2.     initialize: function(options) {  
  3.         this.model.on('change'this.render, this);  
  4.     },  
  5.   
  6.     template: _.template($(‘#template’).html()),  
  7.   
  8.     render: function() {  
  9.         this.$el.html(template(this.model.toJSON());  
  10.         $(‘#a’, this.$el).html(this.model.get(‘a’));  
  11.         $(‘#b’, this.$el).html(this.model.get(‘b’));  
  12.     }  
  13. });  

在这里,任何对模型的改变都会触发整个视图的完全刷新。我第一次用Backbone.js开发时,我是此模式的实践者。但随着视图代码的增长,我很快意识到,这种方式不利于维护或优化,因为模型的任一属性发生改变时,都会触发视图的完全刷新。


当我遇到这个问题,我快速用Google搜索了一下,看别人是怎么做的。结果找到了Ian Storm Taylor的博客,“分解Backbone.js渲染方法”,他在其中描述了在模型中监听单个的属性变化,然后仅仅重新渲染相对于视图中属性变化的那部分。Taylor也描述了返回对象的引用,以便单个渲染函数可以很容易的链接在一起。上面的例子现在就可以修改的易于维护、性能也更优。因为我们只需做视图的部分刷新。


[javascript]   view plain copy print ?
  1. var View = Backbone.View.extend({  
  2.     initialize: function(options) {  
  3.         this.model.on('change:a'this.renderA, this);  
  4.         this.model.on('change:b'this.renderB, this);  
  5.     },  
  6.   
  7.     renderA: function() {  
  8.         $(‘#a’, this.$el).html(this.model.get(‘a’));  
  9.         return this;  
  10.     },  
  11.   
  12.     renderB: function() {  
  13.         $(‘#b’, this.$el).html(this.model.get(‘b’));  
  14.         return this;  
  15.     },  
  16.   
  17.     render: function() {  
  18.         this  
  19.             .renderA()  
  20.             .renderB();  
  21.     }  
  22. });  

我要提醒一下:有不少插件,比如Backbone.StickIt和Backbone.ModelBinder,提供了模型属性与视图元素的键值绑定,这会让你省去编写很多样板代码的时间,所以,如果你需要实现比较复杂的表单字段,那么可以看看这些插件。


五、保持模型与视图无关

正如 Jeremy Ashkenas 在 Backbone.js的GitHub问题中所指出的,Backbone.js并没有实施数据模型与视图层之间的真正分隔,除非模型不是引用视图创建的。因为Backbone.js并没有实施任何关注点分隔,所以你应该将其分离吗?我和许多Backbone.js开发人员,如Oz Katz和Dayal,都相信答案毫无疑问是yes:模型与集合,也就是数据层,应该彻底的与绑定它们的视图无关,保持一个清晰的关注点分离。如果你没有遵循关注点分离,你的代码库会很快变成意大利面条式的代码,而实际上是没有人喜欢意大利面条式的代码。

保持模型与视图无关将会帮助你预防意大利面条式的代码,而没有人喜欢意大利面条式的代码!

保持数据层完全与视图层无关,这会使你创建出更具模块化、可重用和可维护的代码库。你可以很容易地在应用程序各个地方重用和扩展模型与集合,而无需考虑它们所绑定的视图。遵循此模式使对项目不熟悉的新手也能迅速深入到代码库,因为他们会确切地知道哪里发生了渲染,业务逻辑存在于哪里。

这个模式也实现了单一职责原则——它规定了每个类应该具有单个职责,而且它的职责应该封装在类中,因为模型与集合负责处理数据,而视图则负责处理渲染。

六、路由的参数映射

此模式的最佳演示是理解整个例子。比如说对搜索页的结果进行排序,搜索页允许用户添加两个不同的过滤类型,foo和bar,每个类型代表不同的过滤规则。那么,你的URL结构应该是这样:


[javascript]   view plain copy print ?
  1. 'search/:foo'  
  2. 'search/:bar'  
  3. 'search/:foo/:bar'  

现在,所有路由都使用相同的视图和模型,这样大多数人都喜欢用同一个函数search()来实现。然而,你要是检查过Backbone.js代码的话,你会发现它里面没有任何参数映射的排序;这些参数只是从左至右依次传入函数。这样,为了能统一使用同一函数,你要停止创建不同的函数并正确地把参数映射到search()。



[javascript]   view plain copy print ?
  1. routes: {  
  2.     'search/:foo''searchFoo',  
  3.     'search/:bar''searchBar',  
  4.     'search/:foo/:bar''search'  
  5. },  
  6.   
  7. search: function(foo, bar) {      
  8. },  
  9.   
  10. // I know this function will actually still map correctly, but for explanatory purposes, it's left in.  
  11. searchFoo: function(foo) {  
  12.     this.search(foo, undefined);  
  13. },  
  14.   
  15. searchBar: function(bar) {  
  16.     this.search(undefined, bar);  
  17. },  

如你所想,此模式可以使路由功能快速膨胀。当我第一次遇到这个问题时,我试图创建一些正则表达式解析实际的函数定义来实现参数的映射,当然这是可以工作的——但也是受约束的。因此,我放弃了我的这个想法(或许我仍然可以通过BackboneJS的插件来解决)。我进入GitHub的Issues页面,其中Ashkenas建议应该让所有的参数都映射到search函数。 


上面的代码现在可修改为如下的维护性更强的代码:


[javascript]   view plain copy print ?
  1. routes: {  
  2.     'base/:foo''search',  
  3.     'base/:bar''search',  
  4.     'base/:foo/:bar''search'  
  5. },  
  6.   
  7. search: function() {  
  8.     var foo, bar, i;  
  9.   
  10.     for(i = arguments.length - 1; i >= 0; i--) {  
  11.   
  12.         if(arguments[i] === 'something to determine foo') {  
  13.             foo = arguments[i];  
  14.             continue;  
  15.         }  
  16.         else if(arguments[i] === 'something to determine bar') {  
  17.             bar = arguments[i];  
  18.             continue;  
  19.         }  
  20.     }  
  21. },  

此模式可以显著减少路由的过度膨胀。但是,需注意到如果它不能识别参数,则它不会工作。比如,如果你有两个带ID的参数,如模式XXXX-XXXX,那么你不能区分哪个ID是对哪个参数的响应。


七、model.fetch() 不会清除你的模型

通常它会对那些Backbone.js新手造成困扰:model.fetch()不会清除你的模型,而是继承模型的属性。因此,假如模型具有属性x、y和z,你取回y和z,那么属性x仍然是模型中的那个x,而属性y和z会被更新。下面的例子说明了这一点:


[javascript]   view plain copy print ?
  1. var Model = Backbone.Model.extend({  
  2.     defaults: {  
  3.         x: 1,  
  4.         y: 1,  
  5.         z: 1  
  6.     }  
  7. });  
  8. var model = new Model();  
  9. /* model.attributes yields 
  10. { 
  11.     x: 1, 
  12.     y: 1, 
  13.     z: 1 
  14. } */  
  15. model.fetch();  
  16. /* let’s assume that the endpoint returns this 
  17. { 
  18.     y: 2, 
  19.     z: 2, 
  20. } */  
  21. /* model.attributes now yields 
  22. { 
  23.     x: 1, 
  24.     y: 2, 
  25.     z: 2 
  26. } */  

目录
相关文章
|
存储 数据格式 JSON
《BackboneJS框架的技巧及模式》(2)
《BackboneJS框架的技巧及模式》(2) 本文紧接第一部分:《BackboneJS框架的技巧及模式(1)》 作者:chszs,转载需注明。
804 0
|
流计算
《BackboneJS框架的技巧及模式》(3)
《BackboneJS框架的技巧及模式》(3) 本文紧接第二部分:《BackboneJS框架的技巧及模式(2)》 作者:chszs,转载需注明。
864 0
|
JavaScript 前端开发 设计模式
BackboneJS框架的技巧及模式(1)
《BackboneJS框架的技巧及模式》(1) 原文见:http://coding.smashingmagazine.com/2013/08/09/backbone-js-tips-patterns/ 译者注:本文采用意译,省略所有口水话,内容直指要义。
690 0
|
JSON 缓存 ARouter
《BackboneJS框架的技巧及模式》(4)完结篇
《BackboneJS框架的技巧及模式》(4)完结篇 本文紧接第二部分:《BackboneJS框架的技巧及模式(3)》 作者:chszs,转载需注明。
769 0
|
存储 关系型数据库 BI
|
JavaScript 前端开发 Go
《JavaScript框架设计》——1.5 主流框架引入的机制——domReady
domReady其实是一种名为“DOMContentLoaded”事件的别称,不过由于框架的需要,它与真正的DOMContentLoaded有一点区别。在许多旧的JavaScript书藉中,它们都会教导我们把JavaScript逻辑写在window.onload回调中,以防DOM树还没有建完就开始对节点进行操作,导致出错。
1299 0
|
JavaScript 前端开发 数据格式
【JavaScript框架封装】实现一个类似于JQuery的基础框架、事件框架、CSS框架、属性框架、内容框架、动画框架整体架构的搭建
版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81055973 ...
1009 0
|
SQL 前端开发 JavaScript
面向UI编程:ui.js 1.0 粗糙版本发布,分布式开发+容器化+组件化+配置化框架,从无到有的艰难创造
有朋友提出一看来是懵逼的,根本不知道什么是面向UI编程的思想,下面是我之前写的博客,描述的这中思想,下面为地址,参考下就明了很多了。 1. 前端思想实现:面向UI编程        2. 面向UI编程框架:ui.js框架思路详细设计         时隔第一次被UI思路激励,到现在1.0的粗糙版本发布,掐指一算整整半年了。
1382 0
|
20天前
|
开发框架 JavaScript 前端开发
什么是渐进式框架?作用是什么?如何使用?
什么是渐进式框架?作用是什么?如何使用?
11 0
|
存储 缓存 前端开发
【JavaScript框架封装】自己动手封装一个涵盖JQuery基本功能的框架及核心源码分享(单文件版本)
版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81156178 ...
1599 0