JavaScript的Backbone.js框架入门学习指引


Posted in Javascript onMay 07, 2016

1.简介
最近在做一个大型网上银行项目前端的优化,需要使用一个胖客户端的优化,大概思路就是前端通过Ajax 请求去后端获取数据,以Jason的格式返回,然后显示在页面上。由于这个系统非常庞大,胖客户端方案难免需要在客户端写大量的JS代码。我想对于任何团队来说,大量的,非结构化的代码维护起来都非常的不方便。所以BackBone进入了我的视线。
它提供了一种途径可以让你结构化你的JS代码,让你以面向对象的方式来组织你的前端JS代码。这就好比我们在前端应用Domain Driven Design. 我们可以把一个非常大的项目按模块切分。 每个模块里面又可以按照BackBone的要求切分成View,  Model, Router。
通过backbone,你可以把你的数据当作Models,通过Models你可以创建数据,进行数据验证,销毁或者保存到服务器上。当界面上的操作引起model中属性的变化时,model会触发change的事件;那些用来显示model状态的views会接受到model触发change的消息,进而发出对应的响应,并且重新渲染新的数据到界面。在一个完整的backbone应用中,你不需要写那些胶水代码来从DOM中通过特殊的id来获取节点,或者手工的更新HTML页面,因为在model发生变化时,views会很简单的进行自我更新。

2.特点
Backbone是一个轻量级的前端框架,用于结构化管理页面中的大量JS,建立与服务器、视图间的无缝连接,为构建复杂的应用提供基础框架。
下面我先简单地阐述下Backbone的主要特点及特性:

2.1 轻量级
Backbone的源码只有1000行左右(去注释和空行后),文件大小只有16KB,加上依赖库Underscore,也仅有29KB。
你只需要花一点时间,就能轻松了解Backbone内部实现;或编写少量代码,来重载Backbone的部分机制;如果你想在Backbone的基础上做二次开发,也并不是一件复杂的事情。

2.2 结构化
Backbone可以轻松将页面中的数据、逻辑、视图解耦,依照Backbone进行代码结构组织,你可以将项目中的数据交互、业务逻辑、用户界面等工作,分配给多个同事同时开发,并能有序地组织到一起。同时,这对于大型和复杂项目的维护开发非常有帮助。

2.3 继承机制
在Backbone中,模块是可以被继承的,你可以通过面向对象的方式将应用中的数据模型、集合、视图有序地组织,让整个架构更加清晰;也可以方便地重载和扩展自定义方法。

2.4 建立与服务器的无缝连接
在Backbone中内置了一套与服务器数据的交互规则(如果你了解REST架构,就能够轻松地理解它们),而数据的同步工作会在Model中自动进行,前端开发人员只需对客户端数据的进行操作,Backbone会自动将操作的数据同步到服务器。
这是件非常有趣的事情,因为服务器数据接口对前端开发者来说是透明的,他们不需要再关心如何和服务器交互。
然而服务器提供的数据接口也需要兼容Backbone的规则,对于一个新的项目来说,我们可以尝试使用这套规则来构建接口。但如果你的项目中已经有一套稳定的接口,你可能会担心接口改造的风险。
没关系,我们可以通过重载Backbone.sync方法来适配现有的数据接口,针对不同的客户端环境,我们还可以实现不同的数据交互方式。例如:用户通过PC浏览器使用服务时,数据会实时同步到服务器;而用户通过移动终端使用服务时,考虑到网络环境问题,我们可以先将数据同步到本地数据库,在合适的时候再同步到服务器。而这些只需要你重载一个方法就可以实现。

2.5 界面事件管理
在MVC中,我们希望能将界面展现和业务逻辑完全分离,但对于用户产生的交互事件(如单击事件),我们却常常通过类似jQuery中的bind方法进行获取和绑定。
Backbone中的视图帮助我们将用户事件和执行方法有序的组织起来,这只需要我们声明一个简单的表达式,例如:

events: { 
  // 单击id为”save”的元素时,执行视图的add方法 
  'click #save': 'add', 
  'mousedown .button': 'show', 
  'mouseover .button': 'hide' 
}

在表达式中,事件名称可以是任意的DOM事件(如click、mouseover、keypress等),元素可以是jQuery支持的任意选择器(如标签选择器、id选择器、class选择器等)。
视图会自动将表达式中的事件绑定到选择器元素,当元素的事件被触发后,视图会自动调用表达式中绑定的方法。

2.6 轻量级模板解析
模板解析是Underscore中提供的一个方法。为什么我要在介绍Backbone特性时引入Underscore中的方法?因为该方法能帮助我们更好地分离视图结构和逻辑,且Underscore是Backbone必须依赖的库。
模板解析方法能允许我们在HTML结构中混合嵌入JS代码,就像在JSP页面中嵌入Java代码一样:

<ul> 
  <% for(var i = 0; i < len; i++) { %> 
  <li><%=data[i].title%></li> 
  <% } %> 
</li>

通过模板解析,我们不需要在动态生成HTML结构时拼接字符串,更重要的是,我们可以将视图中的HTML结构独立管理(例如:不同的状态可能会显示不同的HTML结构,我们可以定义多个单独的模板文件,按需加载和渲染即可)。

2.7 自定义事件管理

在Backbone中,你可以使用on或off方法绑定和移除自定义事件。在任何地方,你都可以使用trigger方法触发这些绑定的事件,所有绑定过该事件的方法都会被执行,如:

var model = new Backbone.Model(); 
// 在model对象中向自定义事件custom绑定两个函数 
model.on('custom', function(p1, p2) { 
  // todo 
}); 
model.on('custom', function(p1, p2) { 
  // todo 
}); 
// 触发custom事件,将调用上面绑定的两个函数 
model.trigger('custom', 'value1', 'value2'); 
// 移除custom事件中绑定的所有方法 
model.off('custom'); 
// 触发custom事件,但不会执行任何函数,已经事件中的函数已经在上一步被移除 
model.trigger('custom');

如果你熟悉jQuery,你会发现它们与jQuery中的bind、unbind和trigger方法非常类似。
另外,Backbone支持一个特殊事件”all”,当在一个对象中绑定了名为”all”的事件后,该对象在触发任何事件时,都会同时触发”all”事件中绑定的方法。有时这种方法会非常有用,例如我们可以通过”all”事件监听对象状态的变化。

3.路由器
在单页应用中,我们通过JavaScript来控制界面的切换和展现,并通过AJAX从服务器获取数据。
可能产生的问题是,当用户希望返回到上一步操作时,他可能会习惯性地使用浏览器“返回”和“前进”按钮,而结果却是整个页面都被切换了,因为用户并不知道他正处于同一个页面中。
对于这个问题,我们常常通过Hash(锚点)的方式来记录用户的当前位置,并通过onhashchange事件来监听用户的“前进”和“返回”动作,但我们发现一些低版本的浏览器(例如IE6)并不支持onhashchange事件。
Backbone提供了路由控制功能,通过Backbone提供的路由器,我们能通过一个简单的表达式将路由地址和事件函数绑定在一起,例如:

var CustomRouter = Backbone.Router.extend({ 
  routes : { 
    '' : 'index', // 当URL Hash在根目录时执行index方法:url# 
    'list' : 'getList', // 当URL Hash在list节点时执行getList方法:url#list 
    'detail/:id' : 'query', // 当URL Hash在detail节点时执行query方法,并将detail后的数据作为参数传递给query方法:url#list/1001 
    '*error' : 'showError' // 当URL Hash不匹配以上规则时, 执行error方法 
  }, 
  index : function() { 
    alert('index'); 
  }, 
  getList : function() { 
    alert('getList'); 
  }, 
  query : function(id) { 
    alert('query id: ' + id); 
  }, 
  showError : function(error) { 
    alert('error hash: ' + error); 
  }, 
}); 
 
var custom = new CustomRouter(); 
Backbone.history.start();

 
请尝试将这段代码复制到你的页面中,并依次访问以下地址(其中URL表示你的页面地址):

URL
URL#list
URL#detail/1001
URL#hash1
URL#hash2

请再试着使用浏览器的“返回”和“前进”按钮来回切换刚刚输入的地址。

你可以看到,当URL Hash发生变化时,会执行所绑定的方法,当遇到没有定义的Hash时,都会执行showError方法,并将未定义的Hash传递给该方法。

Backbone默认会通过Hash的方式来记录地址的变化,对于不支持onhashchange的低版本浏览器,会通过setInterval心跳监听Hash的变化,因此你不必担心浏览器的兼容性问题。

对于支持HTML5 pushState特性的浏览器,Backbone还允许你通过pushState来创建个性化的URL,但是这需要你的Web服务器做一些适配。
3. Backbone的适用性

Backbone并不像jQuery那样具有非常强的适用性,如果你正准备构建一个大型或复杂的单页Web应用,那么Backbone再适合不过。
如果想将Backbone应用到你的网站页面中,且页面中并没有复杂的逻辑和结构,那么这只会让你的页面更加繁琐和难以维护。
如果你的项目并不复杂,但你却深深喜欢它的某个特性(可能是数据模型、视图管理或路由器),那么你可以将这部分源码从Backbone中抽取出来,因为在Backbone中,各模块间的依赖并不是很强,你能轻易的获取并使用其中的某一个模块。

4. 依赖库

你不能独立使用Backbone,因为它的基础函数、DOM操作、AJAX都依赖于第三方库。

4.1 Underscore
(必选)
Underscore是一个用于提高开发效率的基础函数库,它封装了对集合、数组、对象、函数的常用操作,就像jQuery封装DOM对象一样,你能通过Underscore轻易地访问和操作JavaScript内部对象。
Underscore还提供了一些非常实用的函数方法,如:函数节流、模板解析等。
关于Underscore中一些主要的方法,我会在下一章详细介绍,但在此之前你必须了解:Underscore是Backbone必须依赖的库,因为在Backbone中许多实现都是基于Underscore。

4.2 jQuery和Zepto
(可选)
相信你对jQuery一定不会陌生,它是一个跨浏览器的DOM和AJAX框架。
而对于Zepto你可以理解为“移动版的jQuery”,因为它更小、更快、更适合在移动终端设备的浏览器上运行,它与jQuery语法相同,因此你能像使用jQuery那样使用它。
Zepto目前仅支持Webkit内核的浏览器,因此它能兼容iOS、Adnroid、塞班、黑莓和Meego等大部分移动系统,而对于Windows Phone或Firefox OS,它暂时还不支持。
因为jQuery和Zepto语法相同,因此对于Backbone来说,你无论是使用jQuery还是Zepto,都没有问题(当然,你不可能两个同时都用到)。
在Backbone中,DOM选择器、DOM事件和AJAX,都使用了jQuery的方法。这里之所以所它们是可选的,是假设你没有用到Backbone中的视图和AJAX数据同步功能,那么就不需要导入它们。
如果你不想使用jQuery或Zepto,而是使用其它的、或自定义库,只要你的库中实现了与jQuery语法相同的DOM选择器、事件管理和AJAX方法,那么就不会任何问题。
Backbone允许你通过setDomLibrary方法动态配置需要使用的第三方库,这种情况常常用于:
你的自定义库虽然包含了和jQuery相同语法的方法,但全局变量并不是$,而且你想保持现有的命名。这时你可以通过setDomLibrary方法将其设置为Backbone内部引用的对象。
你希望通过检查用户的环境,来决定更适合使用哪一个库。例如:如果用户使用PC浏览器访问,则载入jQuery,如果用户通过移动终端访问,则载入Zepto。

 

Javascript 相关文章推荐
WEB 浏览器兼容 推荐收藏
May 14 Javascript
jQuery实现默认是闭合的FAQ展开效果菜单
Sep 14 Javascript
jQuery实现横向带缓冲的水平运动效果(附demo源码下载)
Jan 29 Javascript
JS动态插入并立即执行回调函数的方法
Apr 21 Javascript
原生js仿jquery animate动画效果
Jul 13 Javascript
ES6新数据结构Map功能与用法示例
Mar 31 Javascript
JavaScript实现表单注册、表单验证、运算符功能
Oct 15 Javascript
详解Nuxt.js中使用Element-UI填坑
Sep 06 Javascript
Vue+abp微信扫码登录的实现代码示例
Jan 06 Javascript
vue2.x数组劫持原理的实现
Apr 19 Javascript
vue+elementUI(el-upload)图片压缩,默认同比例压缩操作
Aug 10 Javascript
jquery实现穿梭框功能
Jan 19 jQuery
JavaScript数组方法总结分析
May 06 #Javascript
JS平滑无缝滚动效果的实现代码
May 06 #Javascript
使用AJAX实现Web页面进度条的实例分享
May 06 #Javascript
JavaScript中的原型继承基础学习教程
May 06 #Javascript
jquery实现下拉框功能效果【实例代码】
May 06 #Javascript
浅析在javascript中创建对象的各种模式
May 06 #Javascript
jquery自定义插件——window的实现【示例代码】
May 06 #Javascript
You might like
php file_put_contents()功能函数(集成了fopen、fwrite、fclose)
2011/05/24 PHP
解析mysql中UNIX_TIMESTAMP()函数与php中time()函数的区别
2013/06/24 PHP
Zend Framework页面缓存实例
2014/06/25 PHP
php框架CodeIgniter主从数据库配置方法分析
2018/05/25 PHP
Prototype使用指南之dom.js
2007/01/10 Javascript
jquery 之 $().hover(func1, funct2)使用方法
2012/06/14 Javascript
JS的replace方法介绍
2012/10/20 Javascript
js中parseFloat(参数1,参数2)定义和用法及注意事项
2013/01/27 Javascript
js实现在页面上弹出蒙板技巧简单实用
2013/04/16 Javascript
js计算精度问题小结
2013/04/22 Javascript
JS 实现Table相同行的单元格自动合并示例代码
2013/08/27 Javascript
DIV始终居中的js代码
2014/02/17 Javascript
JS倒计时代码汇总
2014/11/25 Javascript
JavaScript 事件入门知识
2015/04/13 Javascript
JQuery操作textarea,input,select,checkbox方法
2015/09/02 Javascript
jqGrid 学习笔记整理——进阶篇(一 )
2016/04/17 Javascript
纯JavaScript 实现flappy bird小游戏实例代码
2016/09/27 Javascript
JS 对java返回的json格式的数据处理方法
2016/12/05 Javascript
微信小程序 列表的上拉加载和下拉刷新的实现
2017/04/01 Javascript
微信页面弹出键盘后iframe内容变空白的解决方案
2017/09/20 Javascript
在antd中setFieldsValue和defaultVal的用法
2020/10/29 Javascript
[01:43]3.19DOTA2发布会 三代刀塔人第三代
2014/03/25 DOTA
[03:58]兄弟们,回来开黑了!DOTA2昔日战友招募宣传视频
2016/07/17 DOTA
python基本语法练习实例
2017/09/19 Python
python selenium 获取标签的属性值、内容、状态方法
2018/06/22 Python
Python批处理更改文件名os.rename的方法
2018/10/26 Python
使用Python调取任意数字资产钱包余额功能
2019/08/15 Python
python实现音乐播放和下载小程序功能
2020/04/26 Python
python3列表删除大量重复元素remove()方法的问题详解
2021/01/04 Python
一篇文章带你学习CSS3图片边框
2020/11/04 HTML / CSS
军训自我鉴定
2013/12/14 职场文书
四川成都导游欢迎词
2014/01/18 职场文书
在校大学生自我评价范文
2014/09/12 职场文书
公司领导班子民主生活会对照检查材料
2014/10/02 职场文书
创业计划书之水果店
2019/07/18 职场文书
java实现对Hadoop的操作
2021/07/01 Java/Android