说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

【前端框架】Backbone.js在大型单页面应用中的应用实践

HTML文档下载 WORD文档下载 PDF文档下载
本文选自《程序员》2013年3月刊,全面介绍了轻量JavaScript MVC框架Backbone.js,并分享了豌豆荚PC客户端借助Backbone.js在开发大型单页面应用上做出的大量实践。

Backbone.js是什么?

Backbone.js是一个JavaScript MVC框架,提供了良好的代码组织能力,可以方便地将应用程序解耦成可以复用的部分,为建立大型的单页面应用提供框架支持,目前的版本是0.9.10(注:现在已到1.2.1版本)。通过将应用程序分解成MVC模式中不同职责的模块,带来了以下几点好处。

  1. 降低维护成本。数据、控制器、视图的更新都是独立进行的,互相之间都是松散耦合的。
  2. 解耦数据和视图,便于直接对业务逻辑进行单元测试。
  3. 便于团队合作,负责UI开发和业务逻辑开发的工程师可以分工并行工作。对于Web前端开发来讲,负责HTML模板和CSS的界面工程师和负责业务逻辑的JavaScript工程师可以协同工作。

Backbone.js算是比较轻量的MVC框架,所谓轻量,是说它只关注一个框架应该关注的最基本的事情——如何给应用分层、如何组织各种功能的代码。至于在实际开发中需要用到的Utils或UI组件,Backbone.js则没有提供任何支持。但Backbone.js所依赖的Underscore.js是一个功能比较全面的非侵入式工具函数类库,算是在Utils方面的一个补充。

轻量并不意味着功能薄弱。首先,Backbone.js的精髓是它定义前端MVC的方式和编码哲学,并依据这些规定了如何去给代码分层,因此Backbone.js能够让前端工程在可维护性和扩展性上都得到质的提升;同时,由于其良好且易于理解的结构,各个模块之间都是松散耦合的,虽然目前官方并没有提供根据实际需求build文件的功能,但如果你愿意,完全可以自己手工删掉源码中的Bakcbone.View只使用Model和Collection;最后,Backbone.js的任何一个部分都是非常容易扩展的。因此,Backbone.js的功能实际上非常强大的。下面将介绍Backbone.js的主要组件(架构如图1所示)。


图1 架构图

Backbone.Events和Backbone.Sync

Backbone.Events和Backbone.Sync两个组件是Backbone.js异步通信、事件驱动的编程模型的基础。

Backbone.js中所有的组件都通过_.extend()的方法“继承”了Backbone.Events所提供的功能,可以维护一套自己的事件订阅和回调列表。通过Events.on(event,[callback],[context])和Events.off([event], [callback], [context])两个方法来实现对事件的订阅和取消订阅。


早期版本中的事件订阅和取消订阅是通过Events.bind()和Events.unbind()两个方法实现的,目前的版本中还保留了这两个别名方法,但不推荐使用。

Backbone.js的所有组件都有一些内置的事件,可以查阅官方文档。除了预置事件外,通过Events.trigger(event,[*args])方法也可以方便地触发自定义事件。


从0.9版开始,Backbone.Events提供了Events.listenTo(other,event,callback)和Events.stopListening([other],[event],[callback])两个新方法来通过另外一种形式实现事件的订阅和取消订阅。

与on()和of f()不同,这种方式将监听的主动权转换了。举个例子来说:有对象A和对象B,B.on('someThingHappened',A.doSomeThing)是当对象BsomeThingHappened时候知对象A去doSomeThing;而A.listenTo(B,'someThingHappend',A.doSomeThing)是对象A主动去盯着对象B,当它someThingHappend的时候去doSomeThing。

第二种方式最大的意义是变被动为主动,从而实现了IoC(Inversionofcontrol,控制反转)。监听者和被监听者之间没有了耦合,只要被监听的对象能够抛出指定的事件,就可以和监听者组合在一起,甚至不需要去关心被监听对象的类型,这对代码的复用和行为抽象有很大的帮助。在测试层面,可以轻易地把被监听对象换成mock的测试代码来模拟真实情况。

Backbone.Sync则将同服务器的通信封装了起来,当Collection和Model需要和服务器通信交换数据时,会去调用Backbone.Sync中对应的方法并发送请求,如果服务器端支持RESTfulAPI就可以将整个通信过程描述得非常优雅并易于扩展。Sync的实现可以是jQuery.ajax()的封装,也可以是其他的类库提供的异步通信工具的封装。

Backbone.Model和Backbone.Collection

Backbone.js中的Model和Collection共同构成了MVC中的M层。Model的本质就是一组以keyvalue形式保存的数据,可以通过Backbone.Model.extend()来定义自己的Model。


上面的示例代码中defaults属性定义了一组默认值,当Model初始化时,如果没有指定defualts中所定义的属性的值,就会用默认值来填充Model;initialize()方法会在Model被实例化时调用,用来进行一些初始化的操作;validate()方法会在Model的save()或set()方法被调用时执行,可以根据具体需求进行扩展。

通过Model的getters和setters可以实现对Model中属性的读写,并且当set()方法被调用时,Model会将属性变化的事件广播给所有订阅者(通常是视图),驱动视图重新渲染或其他关联的Model的数据更新。

Collection是一组Model的集合,通过Collection可以将一组数据结构相同的Model有序地组织在一起,进行批量操作和管理等。同时,Collection代理了Undersore.js中众多用来操作Collection的工具方法,例如find、filter、map等。

Model和Collection都可以通过RESTfulAPI同服务器进行数据交换。

Backbone.View

Backbone.View是基于Backbone.js开发的Web App中的核心部分,负责用户交互事件的捕捉和处理、把用户输入导向Model或Collection、渲染视图、操作DOM等。Backbone.js的内部实现依赖$变量,因此DOM操作的库可以在jQuery、Zepto或Ender等中选择。从目前的情况来看,在桌面浏览器中,Sizzle.js(jQuer y所使用的SelectorEngine)的性能还是甩开Zepto几条街的,因此面向桌面浏览器的开发还是推荐使用jQuery,移动端考虑到文件体积等因素推荐使用Zepto。

对于一个Backbone.View来讲,最重要的就是$el属性,$el是一个jQuery对象(取决于所采用的DOM操作类库),是一个视图的最外层容器。容器所采用的HTML标签可以通过tagName属性来指定,可以是ul也可以是header或其他任何标签,默认情况下是div。

容器内部的DOM渲染可以通过模板引擎来完成。Underscore.js本身提供了一个_.template()的方法,因此Backbone.js不需要额外的模板引擎支持。当然,如果有特殊的需求,例如和后端共用模板文件,也可以选用Mustache等其他的模板引擎。


这样一个View就被渲染到界面上了。上面的代码中还监听了Model的change事件,当数据发生变化时,驱动视图重新渲染。当Model的数据比较丰富时,只有一个属性变化就重新渲染整个视图显然会带来性能上的隐患,因此这里的最佳实践就是把render的过程break-down成粒度更细的片段。


值得注意的是,当一个View不再被需要时,一定要记得销毁,除了销毁DOM对象外,也要销毁所有的事件监听器。在只有Events.on()和Events.off()的年代,由于销毁View时需要逐一取消订阅所有的消息,经常由于忘记解除某个绑定导致产生被称为GhostView的垃圾对象,既无法被释放也无法被回收。这也是Events.listentTo()方法带来的另外一个好处——只要调用Events.stopListening()方法即可将此对象的所有事件监听器销毁。

所有的DOM事件也是通过$el来代理的,在Backbone.View中可以通过以下方法来方便地管理DOM事件。


Backbone.js的内部实现里,在View的构造方法中调用View. initialize( )后将继续调用View.delegateEvents()方法,这个方法将解析events属性所定义的事件和回调列表,并将全部事件代理到$el对象上。由于使用的是事件代理,某些不支持冒泡的DOM事件则必须另外监听,如滚动条事件。


Backbone.Router和Backbone.History

Router是用来在URLHash和特定的动作或视图之间做映射的。


最后一句History.start()是告诉Backbone.js开始对URLHash的变化进行监视,也可以随时通过History.stop()来停止监视。同时,如果目标平台是支持HTML5Histor yAPI的,那么在start时传入{pushstate:true}的参数,就可以去掉URL中的#字符,对SEO有一定帮助。

Backbone.js的适用场景

经常能在各种场合听到前端工程师们讨论“你们的XXX是用什么做的啊?”“为什么不用XXX啊?”这样的问题。前端的类库和框架林林总总,算在一起数量没有一千也有五百,因此在面对一个新项目时难免会产生选择恐惧症。

但说到底,技术方案都是由需求决定的,任何一个类库或框架都有其适用范围和最佳的使用场景,Backbone.js也不例外。Backbone.js的最佳使用场景是大型的单页面应用:通过RESTfulAPI同服务器通信,然后根据数据的变化来驱动视图重新渲染,整个程序建立在异步通信和事件驱动的编程模型之上。

单页面应用给用户带来的使用体验是沉浸式的、相对重型的,对于普通的Web Page和数据相对稳定、视图不需要频繁重新渲染的场景来讲,Backbone.js显然就没有用武之地了。

Backbone.js和MV*不得不说的那点事儿

四十年前,Trygve Reenskaug基于Smartalk语言设计出了MVC模式,经过几十年的发展,MVC出现了众多的衍生。而我们今日说的MVC在不加特殊说明的情况下,通常指的是在服务器端Web应用开发中大量使用的WebMVC。

对于典型MVC模式来讲,View是无法直接获得用户输入的,而Controller则是用户输入和View之间的桥梁。但在浏览器中,View层的载体是HTML,用户输入和交互行为都是基于HTML的,对事件的捕捉、输入都由浏览器代劳了,并且输入会首先进入View层,因此对于前端开发来讲,严格意义的MVC是无法实现的。

因此,包括Backbone.js在内的JavaScript MVC框架的实现并没有严格遵循MVC的定义,Controller的部分职责被转移到了View层。Backbone.js对于前端MVC的定义非常易于理解,但对于没接触过MVC模式的同学来说在初期会有一些迷惑,原因是Backbone.js核心组件的命名。Backbone.js的核心组件包括Backbone.Collection、Backbone.Model、Backbone.View和Backbone.Router,而在早期的版本中,Backbone.Router组件的名称是Backbone.Controller,这很容易让人直接将其和MVC三层中的C层联系起来。但事实上,Backbone.Controller的作用是根据URLHash来在对应的行为和事件中做路由的,其功能同MVC中的C相比要简单很多,因此在0.5前后Controller改名叫做Router了。从实体代码的角度看,View层其实是模板代码和Backbone.View中部分代码的综合体,而Backbone.View中剩余的部分才是MVC模式中Controller的概念,负责操作View以及数据在View和Model层中的流转。

对于前端开发来说,用户直接面对的一层并不是Controller而是View,用户输入也会首先进入View,因而用MVP和MVVM模式来描述架构更加合理。相比AngularJS等框架,Backbone.js的模式显然更易于理解,学习曲线比较平缓,因为它并没有引入过多的需要重新认知和理解的新概念而是尽量在靠近传统的MVC模式,对于以前接触过MVC模式开发的同学来说非常容易上手,而AngularJS中的Directive等概念还是需要一定认知成本的。

但如果从架构的角度讨论,AngularJS其实是更为纯粹并更接近严格意义上的MVC模式。为了把View的功能提升到一个应有的高度,引入了Directive的概念,通过扩展HTML标签和自定义属性来描述View,在Directive中来解析这些扩展出来的内容,理解成本和代码的复杂程度都有所提高,但View层功能则得到了质的提升。

反观Backbone.js,并没有在前端开发中真正的View的载体HTML上做太多文章,即便采用模板引擎也仅仅是把数据和HTML组合起来。但得益于其强大的扩展性,可以很容易将Knockout等Data-binding框架集成进来,从而实现MVVM的架构和分层。例如前文提到将render的过程Breakdown就完全可以用Data-binding来取代,省掉了手工更新DOM的烦琐。

Backbone.js在豌豆荚PC客户端2.0中的实践

豌豆荚PC客户端2.0的UI是完全建立在Web前端基础上的。借助Backbone.js,豌豆荚PC客户端在开发大型单页面应用中做了大量的实践。通过在客户端中捆绑一个Webkit引擎并对其进行扩展,使得跑在Webview中的前端代码跳出沙箱的限制,可以操作文件系统并调用系统API,以此来进行桌面应用的开发。这样做的好处有以下几点。

  1. 极大提高开发效率:桌面应用的开发中,UI开发效率一直很低,但借助HTML5和CSS3的新功能,Web前端可以轻易地做出精细程度和交互体验都不输桌面应用的UI,但开发效率和维护成本都极大降低。
  2. 易于跨平台:UI依赖于Webkit引擎,而Webkit引擎本身是跨平台的,因此可以很容易地移植到Web上或其他桌面平台。
  3. 快速迭代和改进:由于维护和扩展成本的下降,可以快速的将原型设计产品化并进行验证,提高产品迭代和改进的速度。

但与此同时,用Web前端技术开发桌面应用也要面临巨大的挑战。首先就是内存消耗。用户在使用浏览器和使用桌面应用时的心理预期是不一样的,即使一段有内存泄漏问题的前端代码跑在浏览器里,当出现运行缓慢时大不了一下刷新页面,但对桌面应用来讲,大多数情况下没有刷新Webview的机会,因此必须对内存实现更精细的控制。由于Webview本身依赖于GC,前端无法主动管理和回收内存,因此必须借助ChromeDeveloper tools中的Profiles等工具查找出现内存泄漏的地方从而进行改善,这也依赖于大量的经验积累。

其次是运行速度和界面响应速度。由于Webview是单线程的,但单页面应用面临的是数百倍于Web Page的业务逻辑复杂度,同时业务逻辑的执行和UI共用一个线程,如何优化执行速度也是一个很大的挑战。虽然目前WebUI的界面流畅程度无法完全达到桌面应用的水平,但依然是很有竞争力且有提高空间的。(责编:陈秋歌)

作者简介

赵望野:豌豆荚前端团队负责人。

本文选自《程序员》2013年3月刊。2000年创刊至今所有文章目录请查看程序员封面秀。欢迎订阅程序员电子版(含iPad版、Android版、PDF版)。

欢迎加入CSDN前端交流群:218126086,进行前端技术交流。  

重金吸引开发者 BlackBerry10应用36小时增1.5万 把数据中心搬入“空间站” Dell和Intel对OpenStack新兴公司Mirantis投资 快讯:马云自5月10日起不再担任CEO职务 Web工程师必备的43款可视化工具 中国电信天翼开放平台2012年度数据:API调用量破亿 iOS走向开放:UC浏览器iPhone版实现云下载 让Dreamweaver支持cshtml (MVC Razor环境) iOS付费榜首:日历应用Fantastical开发者专访 玩转AdMob移动广告:捕鱼达人的猎财之道 12306抢票插件拖垮GitHub 展望2013 jQuery核心团队成员谈其发展路线 Facebook社交视觉搜索分析:引入“竞价排名”? 移动广告现状5大问题解析 Google将于月底举行Google Glass开发者大赛 分享29个超赞的响应式Web设计 Facebook图谱搜索和谷歌搜索有何不同? Facebook向美国iPhone用户提供免费电话 VMware CTO Steve Herrod离职 加盟风险投资公司 维基百科基金会推出众包旅游项目Wikivoyage 最舒适程序员:工作外包给中国 自己却偷懒 Evernote正在与苹果联合开发硬件记忆工具,未来两年公司上市 Fusion-io发布ioScale 全闪存数据中心时代到来? Agent Dash游戏设计之美:如何用2D打造3D体验? 开源项目文档应规避的13处“硬伤” 李开复:Graph Search将可与谷歌搜索媲美 月成本3500美元 如何在AWS上实现BBVA信用卡低延时分析 外媒眼中的国内互联网巨头:服务器集群庞大但缺乏创新 Facebook主导通用主板+SoC ARM与Intel同台对抗 假如像招聘程序员那样租车…… CrowdStar:Windows Phone 8是开发者的下一片蓝海 VLAN 怎么发电子邮件?? 请问哪里有WideString的定义? 问个关于域名注册的问题 为什么便宜的耳机用一段时间以后,就只有一边发声了?是什么原因?我想自己修,因为手头一大堆这种半报废的耳机 关于属性页的问题,请进 南京上空发现奇异天体 三名飞行员先后紧急报告 我装的weblogic610_win为什么在win2000下运行后打不开http://127.0.0.1:7001/console 有关route add问题 我装的weblogic610_win为什么在win2000下运行后打不开http://127.0.0.1:7001/console VC.NET中是否有支持odbc的类似DBGrid的数据表格控件? 大家推荐一下学习C#的书! htc文件在WEBSPHERE不能正常运行??? 大家在用c编程时,是怎样运用位运算的?(我c学得不好,请大家指教一下) 怎样从一个vlan的客户机访问到另一个vlan上的客户机,急 一个简单问题?关于查询方面的!请指点! htc文件在WEBSPHERE不能正常运行??? 有了Swing,还有必要使用AWT吗? 怎样将richtextbox中的内容存入sql server数据库? 哪位用VC做过拨号程序阿 紧急求援!!!pqmagic在Windows 2000 professional下的安装问题! 如何在PB中通过脚本将文本文件导入数据库中? 一玩3D游戏就退出,一上网就死机,本人用的是小影霸速配3000,何故? 舌尖的热恋(淡月儿) cbuilder5的工程用cbc6打开,编译的时候,出错。为什么?紧急求救!!!!!!!!!! 关于session的问题 如何读取相对路径的文件 我的这点程序怎么运行有错?(内付原码) 编译器错误信息: CS1519: 类、结构或接口成员声明中的标记“(”无效 请教关于VXWORKS的SDK转到LINUX上的方法 有多少人用Struts做过项目啊? 询问所有JSP的高手!!!(在线等) 怎样写一份解决方案 怎样做像qq那样的面板,有源码最好了 还是鼠标事件问题!大家快帮帮忙! 求和的问题 icmp是什么东西,怎么设置?如何打开或关闭它? 抢分啦~~~~ C/C++中有类似于汇编中的宏替换(&)吗? 关于VB的绘图闪烁 哪里有免费空间, 高手必看,微软专家也过来,可能是一个BUG 一个简单的问题! 询问所有ASP的高手!!!(在线等) 请问谁做过类似VC里的界面编辑器的软件 如何处理有"'"单引号的sql语句 菜鸟!!!!!!!!!!!想编一个象棋的程序看看我的思路 cn_robot(创造上帝的猪(CSDN封杀过没脸做人)),你进来!!! 请问怎样添加资源文件 关于积分系统的算法,可以实现必给分,希望大家多提出宝贵意见 《东方时空分家录》据说是中央电视台内部人拍的 JSP电子书?地址? if you had lost of money what would you do?为题目的英语作文 I sent many Christmas cards to my friends.(变为一般疑问句) [] you [] many Christmas cards to [] []怎么看的出来是过去式啊》? it's time (1)home.let's(2).1.to go.to go to .for to .for go to .2.to go.go. 我以后究竟要做什么工作? i sent many beautiful cards___my friends ____ e-mail.(介词填空) There are many buildings on one side of the road,on_____of it,there's some trees.A another sideB.other side C.the other side D.the others side 请解释什么时候用do什么时候用does和什么时候用have什么时候用has he will have exactly half as many cards as his friend是什么意思 There are many trees on______side of the road横线上填什么 “把它挂在墙上”这句话英文怎么翻译? He has sent his friend many e-mails till now.(改为同义句) 1.There are so many trees on___side of the road.2.I saw a lot of trees on___side of the lake.A.all B.both C.either D.every 灯挂在墙上(翻译英文) He wrote few letters to _ of his family,but he sent a few cards to _ of his friends.(any,some)选择适当的不定代词填空 It is an instrument.If we have a cup,some rice or beans,some paper and some string.We can make it by a/an ____ “钟表挂在墙上”用英文怎么说?快 you’ll ,you’ve ,you’d,怎样读?音标? t is an instrument.If we have a cup,some rice or beans,some paper and some string.We can make it by这是什么 位置决定影响,角度决定空间,高度决定视野,态度决定未来是什么广告语 英语翻译我的梦想是实现你的梦想 it is an instrument. if we have a cup,some rice or beans,some paper and some string. We can make it这是什么? 有没有关于七年级下期的英语的三单元的词组 你的梦想就是我的梦想,这句话用英文怎么说知道的给翻译下, After (having) breakfast,my father ofther likes to read newspapers.为什么是h 七年级英语固定词组 一篇用英语写的《我的梦想》《我有一个梦想》 hobbies英文作文爱好是阅读和看电影 最好有中文翻译 英语翻译1.尽快2.校园剧3.出去吃饭4.喜欢结识朋友5.和其他年青人工作6.一份危险的工作7.株洲晚报 英语单词“hobby”有复数吗?如果有,怎么变? There are mang tall trees and colorful flowers on ____ side of the road.A.both B.every C.either D.all选 B 还是 欧共体内部农业较发达的国家有哪些 My friends ___(play) cards now.用所给单词的适当形式填空 There are flowers and trees on ___ side of this road.咋填?a.all b.every c.both d.either请说明原因 英译汉 关于so和neither的倒装句He likes English ,but he doesn`t like maths.______(我也是)用so或neither翻译后半句 hobby复数形式 用所给词的适当形式填空 Let __(we) play ping-pong.My friends用所给词的适当形式填空Let __(we) play ping-pong.My friends often __(play) tennis.He __(play) ping-pong with his classmates after class. nor ,neither ,so 倒装句的谓语用什么一般是前面用什么后面就用什么,如:I am watching TV.So is she.My parents didn’t watch TV last night.Neither did I.但下面两句我不明 If you don’t want it,neither shall I.(为什么 加上一个字母,变成新单词 1、all( ) 2、far( ) 3、air( ) 4、way 关于insect的英语单词 17岁学英语还来得及吗 加上一个字母,变成新单词(英语),far,air,way. insect这个英语单词怎么读? so与neither的区别和句子尽量补充完整! far加一个字母是什么单词 insect是什么的英语单词? 短语翻译:stand empty 在late前加一个字母变新单词是什么?急 _____(she)are my friends.用所给词的正确形式填空These are books in English?用books提问 stand短语都有什么呀,急求,麻烦哪位高人告诉我一些,麻烦了! what did you do yesterday evening?A.I PLAYED chess with my friend B.i am looking for my schoolbagc.i like walking to schoold.i want to buy a pencli 公司的晚上上我中了大奖,要说获奖感言怎么说. 类似于 stand by me 这种简单的英语小短句. we played football with our friends yesterday用every day改写 谁能帮我写一篇关于感恩企业的演讲稿! 七年级英语中值得特别注意的几个介词短语有哪些?lg:在树上、在墙上、在.的前面、在.的后面等. hobby 是可数名词吗 5.It's time ________ lunch.Let's go home.A.to B.in C.for D.on What would you do if you had much money?(改为同义句)()()you had much money?Did you use computers to make the foreign language easy to learn?(改为同义句)()computers ()to help you learn the foreign language()?We will be ha 英语翻译Rain ,Rain ,go away come again some other day little Johnny wants to play Rain ,Rain ,go away Rain ,Rain ,go away come again some other day little Johnny wants to play Rain ,Rain ,go away 先进个人获奖感言,保安队先进个人获奖感言
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘