《BackboneJS框架的技巧及模式》(2)
《BackboneJS框架的技巧及模式》(2)
本文紧接第一部分:《BackboneJS框架的技巧及模式(1)》
作者:chszs,转载需注明。博客主页:http://blog.csdn.net/chszs
二、为对象创建Façade外观模式
在实际项目中,需求是经常变化的,因此,终端返回的JSON数据格式也是如此。如果你的视图和下层的数据模型是紧耦合的,那么这是一种痛苦。有鉴于此,我为所有的对象都创建getter和setter函数。
此模式使用较广。如果任何底层的数据结构发生了变化,那么视图层无需随之更新;你会有一个数据访问点,所以你不太可能忘记做深度复制,编写的代码将会更易于维护和调试。此模式的缺点在于它可能会导致模型或集合有一点点膨胀。
下面我们看一个例子来阐明此模式。假想我们有一个Hotel模型,它包含了rooms和当前有效的rooms,而且我们希望可以通过床位大小来获取rooms。
var Hotel = Backbone.Model.extend({
defaults: {
"availableRooms": ["a"],
"rooms": {
"a": {
"size": 1200,
"bed": "queen"
},
"b": {
"size": 900,
"bed": "twin"
},
"c": {
"size": 1100,
"bed": "twin"
}
},
getRooms: function() {
$.extend(true, {}, this.get("rooms"));
},
getRoomsByBed: function(bed) {
return _.where(this.getRooms(), { "bed": bed });
}
}
});
现在我们假设明天你要发布项目,但你发现终端开发者忘记告诉你rooms的数据结构发生了修改。你的代码现在看起来会像下面这样:
var Hotel = Backbone.Model.extend({
defaults: {
"availableRooms": ["a"],
"rooms": [
{
"name": "a",
"size": 1200,
"bed": "queen"
},
{
"name": "b",
"size": 900,
"bed": "twin"
},
{
"name": "c",
"size": 1100,
"bed": "twin"
}
],
getRooms: function() {
var rooms = $.extend(true, {}, this.get("rooms")),
newRooms = {};
// transform rooms from an array back into an object
_.each(rooms, function(room) {
newRooms[room.name] = {
"size": room.size,
"bed": room.bed
}
});
},
getRoomsByBed: function(bed) {
return _.where(this.getRooms(), { "bed": bed });
}
}
});
我们仅修改了一个函数,以便将Hotel的结构转变为应用程序所期望的结构,以便整个应用程序仍然能像我们所预期的那样工作。如果这里没有getter函数,我们很可能不得不为rooms的每个访问点进行代码修改。理想情况下,你会修改所有函数,以适应新的数据结构,但如果你有项目发布的时间压力,此模式可以为你节省时间。
顺便说一句,此模式既可以被认为是Facade装饰模式,因为它隐藏了创建对象复制的复杂性,也可以认为是Bridge桥接模式,因为它可以用于将数据转换为所期望的格式。
最佳实践是对任何对象都使用getters 和setters 函数。
三、不通过服务器存储数据
尽管Backbone.js有模型和集合映射到RESTful端点的规则,有时候你可能会花大量时间查找你想要的存储在服务器端的数据或集合。
有一些关于Backbone.js的文章,描述了此模式。下面让我们一起来快速看一个小例子。假设你有一个ul元素列表。
<ul>
<li><a href="#" data-id="1">One</a></li>
<li><a href="#" data-id="2">Two</a></li>
. . .
<li><a href="#" data-id="n">n</a></li>
</ul>
列表有200项,当使用者点击列表中的某项时,选择的项变成被选中状态:
var Model = Backbone.Model.extend({
defaults: {
items: [
{
"name": "One",
"id": 1
},
{
"name": "Two",
"id": 2
},
{
"name": "Three",
"id": 3
}
]
}
});
var View = Backbone.View.extend({
template: _.template($('#list-template').html()),
events: {
"#items li a": "setSelectedItem"
},
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
},
setSelectedItem: function(event) {
var selectedItem = $(event.currentTarget);
// Set all of the items to not have the selected class
$('#items li a').removeClass('selected');
selectedItem.addClass('selected');
return false;
}
});
<script id="list-template" type="template">
<ul id="items">
<% for(i = items.length - 1; i >= 0; i--) { %>
<li>
<a href="#" data-id="<%= item[i].id %>"><%= item[i].name %></a></li>
<% } %></ul>
</script>
现在我们能很容易的判断被选中的项,并且我们没有必要通去遍历列表。而且,如果列表非常大,遍历会是一个巨大的开销。因此,当用户点击了列表项后,我们应该存储被选择了的项。
var View = Backbone.View.extend({
initialize: function(options) {
// Re-render when the model changes
this.model.on('change:items', this.render, this);
},
template: _.template($('#list-template').html()),
events: {
"#items li a": "setSelectedItem"
},
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
},
setSelectedItem: function(event) {
var selectedItem = $(event.currentTarget);
// Set all of the items to not have the selected class
$('#items li a').removeClass('selected');
selectedItem.addClass('selected');
// Store a reference to what item was selected
this.selectedItemId = selectedItem.data('id'));
return false;
}
});
现在我们可以很容易的确定哪些项被选中了,并且我们无需遍历DOM模型。此模式对于存储外部数据来说非常有用,请记住,你可以创建不需有端点相关联的且存储外部视图数据的模型和集合。
此模式的缺点是如果你存储了外部数据到你的模型或集合,它们不能真正遵循RESTful架构,因为它们不能完美的映射Web资源;另外,此模式可能会引起对象的膨胀;如果端点是严格接受JSON格式,那么它可能会引起一些烦恼。
你或许会问自己,“我如何确定我是否应该把外部数据放进视图或者放进模型?”。如果你为呈现添加了额外的属性,例如容器的高度,那么我们把它添加到视图。如果此属性跟下层的数据模型有一定的关系,然后你想把它放进模型。总之一句话,根据实际的需求进行判断。
《BackboneJS框架的技巧及模式》(2)的更多相关文章
- 《从零开始做一个MEAN全栈项目》(1)
欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 在本系列的开篇,我打算讲一下全栈项目开发的优势,以及MEAN项目各个模块的概览. 为什么选择全栈开发? ...
- 《从零开始做一个MEAN全栈项目》(2)
欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 上一节简单介绍了什么是MEAN全栈项目,这一节将简要介绍三个内容:(1)一个通用的MEAN项目的技 ...
- 《从零开始做一个MEAN全栈项目》(3)
欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 上一篇文章给大家讲了一下本项目的开发计划,这一章将会开始着手搭建一个MEAN项目.千里之行,始于足下, ...
- 《从零开始做一个MEAN全栈项目》(4)
欢迎关注本人的微信公众号"前端小填填",专注前端技术的基础和项目开发的学习. 在上一篇中,我们讲了如何去构建第一个Express项目,总结起来就是使用两个核心工具,express和 ...
- 一个关于vue+mysql+express的全栈项目(一)
最近学了mysql数据库,寻思着能不能构思一个小的全栈项目,思来想去,于是就有了下面的项目: 先上几张效果图吧 目前暂时前端只有这几个页面,后端开发方面,有登录,注册,完善用户信息,获取用 ...
- Vue、Nuxt服务端渲染,NodeJS全栈项目,面试小白的博客系统~~
Holle,大家好,我是李白!! 一时兴起的开源项目,到这儿就告一段落了. 这是一个入门全栈之路的小项目,从设计.前端.后端.服务端,一路狂飙的学习,发量正在欣喜若狂~~ 接触过WordPress,H ...
- Vue、Node全栈项目~面向小白的博客系统~
个人博客系统 前言 ❝ 代码质量问题轻点喷(去年才学的前端),有啥建议欢迎联系我,联系方式见最下方,感谢! 页面有啥bug也可以反馈给我,感谢! 这是一套包含前后端代码的个人博客系统,欢迎各位提出建议 ...
- SpringBoot 整合 Elastic Stack 最新版本(7.14.1)分布式日志解决方案,开源微服务全栈项目【有来商城】的日志落地实践
一. 前言 日志对于一个程序的重要程度不用过多的言语修饰,本篇将以实战的方式讲述开源微服务全栈项目 有来商城 是如何整合当下主流日志解决方案 ELK +Filebeat . 话不多说,先看实现的效果图 ...
- 全栈项目|小书架|服务器端-NodeJS+Koa2实现首页图书列表接口
通过上篇文章 全栈项目|小书架|微信小程序-首页水平轮播实现 我们实现了前端(小程序)效果图的展示,这篇文章来介绍服务器端的实现. 首页书籍信息 先来回顾一下首页书籍都有哪些信息: 从下面的图片可以看 ...
- 全栈项目|小书架|服务器开发-NodeJS 使用 JWT 实现登录认证
通过这篇 全栈项目|小书架|服务器开发-JWT 详解 文章我们对JWT有了深入的了解,那么接下来介绍JWT如何在项目中使用. 安装 $ npm install jsonwebtoken 生成 Toke ...
随机推荐
- Mac 安装maven3.3.9
只记录一部分自己出错的内容 maven 3 与 jdk 版本的关系 之前安装的jdk是1.8 安装完maven(包括配置环境变量)之后,输入mvn -version 显示版本错误 ,百度之后发现是ma ...
- iOS开发之通知中心(NSNotificationCenter)
前言 面向对象的设计思想是把行为方法封装到每一个对象中,以用来增加代码的复用性.正是这种分散封装,增加了对象之间的相互关联,总是有很多的对象需要彼此了解以及相互操作! 一个简单示例说明这种交互产生的对 ...
- ThinkPHP 的CURD 基本操作
说起CURD,懂点SQL的人都知道,就是增删改查,做业务系统的时候,往往离不开这CURD,最近也是刚刚接触ThinkPHP,ThinkPHP的灵活性是比原生PHP好用的多,下面我就简单的介绍一下我的学 ...
- 【NOI2006】最大获利
[问题描述] 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU 集团旗下的CS&T 通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就 ...
- 安装SVN及实现nginx web同步更新需要在WDCP一键安装包的基础上
一.安装 1.查看是否安装cvs rpm -qa | grep subversion 2.安装 yum install subversion 3.测试是否安装成功 /usr/bin/svnserve ...
- EF学习系列
http://www.cnblogs.com/Wayou/archive/2012/09/20/EF_CodeFirst.html http://kb.cnblogs.com/zt/ef/#
- (转)ligerUI 使用教程之Tip介绍与使用
概述: ligertip是ligerUI系列插件中的tooltip类插件,作用是弹一个浮动层,起提示作用 阅读本文要求具备jQuery的基本知识,不然文中的javascript代码不易理解 截 ...
- UVA 572 Oil Deposits油田(DFS求连通块)
UVA 572 DFS(floodfill) 用DFS求连通块 Time Limit:1000MS Memory Limit:65536KB 64bit IO Format: ...
- d038: 星罗密布
内容: 输出图形 *****$***$$$*$$$$$ 规律是...自己发现吧. 要求输入3,输出上面三行的图形 输入说明: 行数小于40 输出说明: 输入样例: 3 输出样例 : ***** ...
- API风格
Client------------ Request ----------------->多Server端 Server------------------------------------- ...