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

简介: 二、为对象创建Fa?ade外观模式 在实际项目中,需求是经常变化的,因此,终端返回的JSON数据格式也是如此。如果你的视图和下层的数据模型是紧耦合的,那么这是一种痛苦。

二、为对象创建Fa?ade外观模式

在实际项目中,需求是经常变化的,因此,终端返回的JSON数据格式也是如此。如果你的视图和下层的数据模型是紧耦合的,那么这是一种痛苦。有鉴于此,我为所有的对象都创建getter和setter函数。

此模式使用较广。如果任何底层的数据结构发生了变化,那么视图层无需随之更新;你会有一个数据访问点,所以你不太可能忘记做深度复制,编写的代码将会更易于维护和调试。此模式的缺点在于它可能会导致模型或集合有一点点膨胀。

下面我们看一个例子来阐明此模式。假想我们有一个Hotel模型,它包含了rooms和当前有效的rooms,而且我们希望可以通过床位大小来获取rooms。


[javascript]   view plain copy print ?
  1. var Hotel = Backbone.Model.extend({  
  2.     defaults: {  
  3.         "availableRooms": ["a"],  
  4.         "rooms": {  
  5.             "a": {  
  6.                 "size": 1200,  
  7.                 "bed""queen"  
  8.             },  
  9.             "b": {  
  10.                 "size": 900,  
  11.                 "bed""twin"  
  12.             },  
  13.             "c": {  
  14.                 "size": 1100,  
  15.                 "bed""twin"  
  16.             }  
  17.         },  
  18.   
  19.         getRooms: function() {  
  20.             $.extend(true, {}, this.get("rooms"));  
  21.         },  
  22.   
  23.         getRoomsByBed: function(bed) {  
  24.             return _.where(this.getRooms(), { "bed": bed });  
  25.         }  
  26.     }  
  27. });  

现在我们假设明天你要发布项目,但你发现终端开发者忘记告诉你rooms的数据结构发生了修改。你的代码现在看起来会像下面这样:



[javascript]   view plain copy print ?
  1. var Hotel = Backbone.Model.extend({  
  2.     defaults: {  
  3.         "availableRooms": ["a"],  
  4.         "rooms": [  
  5.             {  
  6.                 "name""a",  
  7.                 "size": 1200,  
  8.                 "bed""queen"  
  9.             },  
  10.             {  
  11.                 "name""b",  
  12.                 "size": 900,  
  13.                 "bed""twin"  
  14.             },  
  15.             {  
  16.                 "name""c",  
  17.                 "size": 1100,  
  18.                 "bed""twin"  
  19.             }  
  20.         ],  
  21.   
  22.         getRooms: function() {  
  23.             var rooms = $.extend(true, {}, this.get("rooms")),  
  24.              newRooms = {};  
  25.   
  26.             // transform rooms from an array back into an object  
  27.             _.each(rooms, function(room) {  
  28.                 newRooms[room.name] = {  
  29.                     "size": room.size,  
  30.                     "bed": room.bed  
  31.                 }  
  32.             });  
  33.         },  
  34.   
  35.         getRoomsByBed: function(bed) {  
  36.             return _.where(this.getRooms(), { "bed": bed });  
  37.         }  
  38.     }  
  39. });  

我们仅修改了一个函数,以便将Hotel的结构转变为应用程序所期望的结构,以便整个应用程序仍然能像我们所预期的那样工作。如果这里没有getter函数,我们很可能不得不为rooms的每个访问点进行代码修改。理想情况下,你会修改所有函数,以适应新的数据结构,但如果你有项目发布的时间压力,此模式可以为你节省时间。


顺便说一句,此模式既可以被认为是Facade装饰模式,因为它隐藏了创建对象复制的复杂性,也可以认为是Bridge桥接模式,因为它可以用于将数据转换为所期望的格式。

最佳实践是对任何对象都使用getters 和setters 函数。

三、不通过服务器存储数据

尽管Backbone.js有模型和集合映射到RESTful端点的规则,有时候你可能会花大量时间查找你想要的存储在服务器端的数据或集合。

有一些关于Backbone.js的文章,描述了此模式。下面让我们一起来快速看一个小例子。假设你有一个ul元素列表。


[html]   view plain copy print ?
  1. ul>  
  2.     li>a href="#" data-id="1">Onea>li>  
  3.     li>a href="#" data-id="2">Twoa>li>  
  4.     . . .  
  5.     li>a href="#" data-id="n">na>li>  
  6. ul>  

列表有200项,当使用者点击列表中的某项时,选择的项变成被选中状态:



[javascript]   view plain copy print ?
  1. var Model = Backbone.Model.extend({  
  2.     defaults: {  
  3.         items: [  
  4.             {  
  5.                 "name""One",  
  6.                 "id": 1             
  7.             },  
  8.             {  
  9.                 "name""Two",  
  10.                 "id": 2             
  11.             },  
  12.             {  
  13.                 "name""Three",  
  14.                 "id": 3             
  15.             }  
  16.         ]  
  17.     }  
  18. });  
  19.   
  20. var View = Backbone.View.extend({  
  21.     template: _.template($('#list-template').html()),  
  22.   
  23.     events: {  
  24.         "#items li a""setSelectedItem"  
  25.     },  
  26.   
  27.     render: function() {  
  28.         $(this.el).html(this.template(this.model.toJSON()));  
  29.     },  
  30.   
  31.     setSelectedItem: function(event) {  
  32.         var selectedItem = $(event.currentTarget);  
  33.         // Set all of the items to not have the selected class  
  34.         $('#items li a').removeClass('selected');  
  35.         selectedItem.addClass('selected');  
  36.         return false;  
  37.     }  
  38. });  
  39.  type="template">  
    • "items"
    >  
  40.         for(i = items.length - 1; i >= 0; i--) { %>  
  41.     
  42.   
  43.                 "#" data-id="">   
  44.   
  45.   

现在我们能很容易的判断被选中的项,并且我们没有必要通去遍历列表。而且,如果列表非常大,遍历会是一个巨大的开销。因此,当用户点击了列表项后,我们应该存储被选择了的项。



[javascript]   view plain copy print ?
  1. var View = Backbone.View.extend({  
  2.     initialize: function(options) {  
  3.         // Re-render when the model changes  
  4.         this.model.on('change:items'this.render, this);  
  5.     },  
  6.   
  7.     template: _.template($('#list-template').html()),  
  8.   
  9.     events: {  
  10.         "#items li a""setSelectedItem"  
  11.     },  
  12.   
  13.     render: function() {  
  14.         $(this.el).html(this.template(this.model.toJSON()));  
  15.     },  
  16.   
  17.     setSelectedItem: function(event) {  
  18.         var selectedItem = $(event.currentTarget);  
  19.         // Set all of the items to not have the selected class  
  20.         $('#items li a').removeClass('selected');  
  21.         selectedItem.addClass('selected');  
  22.         // Store a reference to what item was selected  
  23.         this.selectedItemId = selectedItem.data('id'));  
  24.         return false;  
  25.     }  
  26. });  

现在我们可以很容易的确定哪些项被选中了,并且我们无需遍历DOM模型。此模式对于存储外部数据来说非常有用,请记住,你可以创建不需有端点相关联的且存储外部视图数据的模型和集合。


此模式的缺点是如果你存储了外部数据到你的模型或集合,它们不能真正遵循RESTful架构,因为它们不能完美的映射Web资源;另外,此模式可能会引起对象的膨胀;如果端点是严格接受JSON格式,那么它可能会引起一些烦恼。

你或许会问自己,“我如何确定我是否应该把外部数据放进视图或者放进模型?”。如果你为呈现添加了额外的属性,例如容器的高度,那么我们把它添加到视图。如果此属性跟下层的数据模型有一定的关系,然后你想把它放进模型。总之一句话,根据实际的需求进行判断。

目录
相关文章
|
3月前
|
前端开发 Java UED
JSF 面向组件开发究竟藏着何种奥秘?带你探寻可复用 UI 组件设计的神秘之路
【8月更文挑战第31天】在现代软件开发中,高效与可维护性至关重要。JavaServer Faces(JSF)框架通过其面向组件的开发模式,提供了构建复杂用户界面的强大工具,特别适用于设计可复用的 UI 组件。通过合理设计组件的功能与外观,可以显著提高开发效率并降低维护成本。本文以一个具体的 `MessageComponent` 示例展示了如何创建可复用的 JSF 组件,并介绍了如何在 JSF 页面中使用这些组件。结合其他技术如 PrimeFaces 和 Bootstrap,可以进一步丰富组件库,提升用户体验。
55 0
|
JavaScript 前端开发 C#
如何将现有的Blazor项目的主题切换写的更好看?
如何将现有的Blazor项目的主题切换写的更好看?
105 1
|
前端开发 JavaScript 开发者
封装库/工具库中重要概念之UI框架
UI(User Interface)框架是前端开发中十分重要的一部分,它提供了各种组件和样式,用于构建页面和用户界面。在前端开发中,封装库/工具库可以帮助我们更加高效地使用 UI 框架。
195 0
|
开发框架 .NET 中间件
浅入ABP(1):搭建基础结构的 ABP 解决方案
浅入ABP(1):搭建基础结构的 ABP 解决方案
157 0
浅入ABP(1):搭建基础结构的 ABP 解决方案
|
缓存 .NET 开发框架
【ABP框架系列学习】N层架构(3)
原文:【ABP框架系列学习】N层架构(3) 目录 0.引言 1.DDD分层 2.ABP应用构架模型 客户端应用程序(Client Applications) 表现层(Presentation Layer) 分布式服务层(Distributed Service Layer) 应用层(Application Layer) 领域层 基础设施层 3.使用ABP项目模版快速生成应用程序 0.引言 应用程序的分层是一种广泛接受的技术, 可以降低复杂度和提高代码的可重用性。
1731 0
|
Web App开发 前端开发 .NET
【ABP框架系列学习】模块系统(4)
原文:【ABP框架系列学习】模块系统(4) 0.引言 ABP提供了构建模块和通过组合模块以创建应用程序的基础设施。一个模块可以依赖于另外一个模块。通常,程序集可以认为是模块。如果创建多个程序集的应用程序,建议为每个程序集创建模块定义。
1601 0
|
存储 缓存 前端开发
【JavaScript框架封装】自己动手封装一个涵盖JQuery基本功能的框架及核心源码分享(单文件版本)
版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81156178 ...
1642 0
|
JavaScript 前端开发 数据格式
【JavaScript框架封装】实现一个类似于JQuery的基础框架、事件框架、CSS框架、属性框架、内容框架、动画框架整体架构的搭建
版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81055973 ...
1033 0
|
JavaScript 前端开发
|
存储 关系型数据库 BI