Backbine.js实战第七章----导航控制器

来源:互联网 发布:矩阵张量积 编辑:程序博客网 时间:2024/05/20 21:52

    在前面的章节中曾提到,Backbone框架的最佳应用场景是构建一个逻辑复杂的单页应用,即单页富应用。随着人名对这种应用的喜爱,希望提供或搜藏应用在某一阶段的URL或锚点地址,方便日后直接进入这个阶段的功能页。

    为了满足这种需求,实现在单页富应用中通过锚点或特殊格式的URL完成可分享、可收藏的功能,Backbone框架中提供了两个重要的模型——导航控制器(router)和历史(history),router封装了兼容各类浏览器history的方案,通过使用浏览器的hash对象和HTML5中的pushState方法,将某阶段特殊的URL或锚点地址与既定的事件(event)或函数(action)相绑定。输入这些URL地址时,对应完成不同的功能,从而实现在单页富应用中分享和收藏的功能。


7.1 浏览器导航基础

    在正式介绍Backbone中的导航控制器(router)之前,有必要了解下浏览器的导航功能基础知识,包含浏览器窗口(window)的history、HTML5中history API和location对象。了解这些基础知识,有利于对Backbone中的导航控制器工作原理的理解和掌握。

7.1.1 history对象

    在编写JavaScript代码中,经常用到history对象,它的功能是保存浏览器的历史浏览记录。出于对用户隐私和安全性的考虑,history对象可以使用的方法相对较少,其中有两个比较常用的方法——back和forward。

    (1)back方法的功能是返回浏览器历史记录中当前页的上一页,与浏览器的“后退”按钮功能相同,调用格式如下。

     window.history.back();

    (2)forward方法的功能是进入浏览器历史记录中当前页的下一页,与浏览器的“前进”按钮功能相同,调用格式如下。

     window.history.forward();

     接下来通过一个简单示例进行介绍。

              示例 7-1 history对象的方法

1.功能描述    

    在项目中,新建两个用于互访的页面7-1-a.html和7-1-b.html。在第一个页面中添加一个按钮和一个超级链接元素,如果在history对象中存在已前进的历史记录,则隐藏超级链接元素,否则隐藏按钮。单击超链接元素时,进入7-1-b.html页面,单击按钮时,进入历史记录中当前页的下一页。在第二个页面中添加一个按钮,单击该按钮时,返回历史记录中当前页的上一页。

文件7-1-a.html内容

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title><script src="../script/jquery-1.11.1.js"></script><script src="../script/underscore.js"></script><script src="../script/backbone.js"></script><style type="text/css">body{font-size:12px;}</style></head><body><input type="button" id="btnforward" value="前进" onclick="window.history.forward();"><a href="7-1-b.html" id="lnkforward">前进</a></body><script type="text/javascript">var $obj_wh = window.history;if($obj_wh.length>2){$("#lnkforward").css("display","none");}else{$("#btnforward").css("display","none");}</script></html>
文件7-1-b.html内容

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title><script src="../script/jquery-1.11.1.js"></script><script src="../script/underscore.js"></script><script src="../script/backbone.js"></script><style type="text/css">body{font-size:12px;}</style></head><body><input type="button" value="后退" onclick="window.history.back();"/></body></html>


2.源码分析

    在本示例第一个页面的JavaScript代码中,首先定义一个名为“$obj_wh”的变量用于保存history对象。该对象的length值大于2时,表示在该对象中已存在当前页的下一页连接。通过history对象length值跟踪发现。首次打开浏览器时,该属性值为1,而浏览第一个页面地址时,该属性值又变为2。可见,每浏览一个新的地址时,都会向history对象中添加一条记录,而对应的length属性值有会相应地增加1。所以该属性值大于2时,表名浏览器已打开过本示例的第二个页面,因此就会隐藏链接元素,显示“前进”按钮。

    在第一个页面添加“前进”按钮时绑定onclick事件,单击该按钮时,将调用history对象中的forward方法直接进入当前页历史记录中的下一页。

    在第二个页面添加“后退”按钮时绑定onclick事件,单击该按钮时,将调用history对象中的back方法直接进入当前页历史记录的上一页。

    在history对象中,调用该对象forward和back方法分别实现页面的前进和后退功能外,直接调用对象的go方法,也能实现页面的前进和后退功能,调用格式如下。

    winodw.history.go(n);

    其中,参数n为一个整数,大于0时表示前进,小于0时表示后退,因此,如果是用于实现页面的前进功能,下面代码是等价的。

    window.history.forward();

    等价于:

    window.history.go(1);

    如果是用于实现页面的后退功能,则下列代码也是等价的。

    window.history.back();

    等价于:

    window.history.go(-1);



7.1.2 HTML5中history对象API

    上一节针对HTML4标准介绍了history对象的常用方法。HTML5基于原有对象方法新增了两个实用的API方法。

   (1)pushState方法:功能是向历史记录堆栈的顶部添加一条记录,常用于实现页面的无刷新跳转,其调用格式如下。

     window.history.pushState(data,title[,url]);

    其中,data参数表示在添加记录时传递的数据对象,该对象通常为JSON格式的字符串;参数title为页面显示的标题,可选项参数为页面跳转地址,默认值为当前页地址。

   (2)replaceState方法:功能是修改当前的历史记录值,其调用格式如下。

    window.history.replaceState(data,title[,url]);

    其中,各个从参数的使用说明与pushState方法相同,不再赘述。

    此外,history对象还有一个重要的state属性,通过该属性可以获取使用pushState方法新增的实体对象的内容,即在使用pushState方法增加时data参数的实体值,它的调用格式如下。

    window.history.state;

    目前,各个浏览器对HTML5标准支持不全面,在使用history对象两个新增的API方法时,首先需要检测浏览器对它的支持状态,检测代码如下。

function supports_history_api(){return !!(window.history&&history.pushState);}
    调用上面的自定义函数,如果返回值为true,表示支持history对象新增的API方法,否则表示浏览器不支持history对象或新增的API方法。

    接下来通过一个简单示例进行介绍。 
              示例 7-2 HTML5中history对象的方法

1.功能描述 

    在项目中新建两个页面7-2-a.html和7-2-b.html用于互访。在第一个页面中,添加两个<div>和<span>元素,调用history对象的pushState方法时,分别显示history对象当前新增的历史记录实体总量和内容;在第二个页面中,同样添加两个<div>he  <span>元素,调用history对象的replaceState方法时,分别显示history对象当前替换后的历史记录实体总量和内容。

文件7-2-a.html内容

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title><script src="../script/jquery-1.11.1.js"></script><script src="../script/underscore.js"></script><script src="../script/backbone.js"></script><style type="text/css">div{margin:5px 0px;font-size:13px;}</style></head><body><div>记录总量:<span id="divNum"></span></div><div>刷新前:<span id="divShow"></span></div></body><script type="text/javascript">var obj_a_state = {Code:"10107",Name:"皮卡丘",Score:750};window.history.pushState(obj_a_state,"HTML5中history API方法","7-2-b.html");$("#divNum").html(history.length);$("#divShow").html(JSON.stringify(window.history.state));</script></html>
文件7-2-b.html内容

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title><script src="../script/jquery-1.11.1.js"></script><script src="../script/underscore.js"></script><script src="../script/backbone.js"></script><style type="text/css">div{margin:5px 0px;font-size:13px;}</style></head><body><div>记录总量:<span id="divNum"></span></div><div>刷新前:<span id="divShow"></span></div></body><script type="text/javascript">var obj_b_state = {Code:"10108",Name:"杰尼龟",Score:950};window.history.replaceState(obj_b_state,"HTML5中history API方法");$("#divNum").html(history.length);$("#divShow").html(JSON.stringify(window.history.state));</script></html>

2.源码分析

    在7-2-a.html页面的JavaScript代码中,首先定义一个名称为“obj_a_state”的JSON格式对象,然后调用history对象中的pushState方法将该对象的内容插入当前历史记录的顶部,作为当前历史记录的实体对象。同时设置titile和url参数值,使页面在无刷新的情况下,动态将当前的地址修改为url参数传来的地址。最后,将history对象的记录总数和state属性内容分别显示在页面指定的元素中。

    首次打开7-2-a.html页面后,虽然将当前页的地址修改为url参数传过来的地址,即将当前页的地址修改为7-2-b.html,但仅限于修改,其实并没有执行该地址。用户此时单击页面导航条中的刷新按钮时,将真正浏览7-2-b.html页。在该页面的JavaScript代码中,调用history对象中的replaceState方法替换当前历史记录的对象,并将替换后的history对象记录项总量和state属性内容分别显示在页面指定的元素中。从上图中可以看出,在记录项总量未变的情况下,history对象state属性内容发生了变化,说明替换成功。


7.1.3 location对象

    在浏览器窗口(window)中,location对象的功能是管理浏览器的地址。相对于history对象而言,该对象拥有更多实用的属性和方法,如最常用的href属性和reload方法,前者可以获取当前浏览器的地址,后者方法可以重新按地址加载当前页面。此外,还能通过调用location对象其他属性,获取浏览器地址的各个组成部分,其属性与地址组成部分对应关系如下图所示。


    从上图可以看出,浏览器中URL地址的各个组成部分都可以通过调用location对象的属性获取,操作也十分方便。接下来通过一个简单示例进行介绍。

              示例 7-3 location对象的属性和方法

1.功能描述 

    在页面中添加一个<div>元素,用于显示遍历location对象后获取的对象方法和各个属性值的内容。另外添加两个按钮元素,单击“重载”按钮时,重新加载当前页面,单击“替换”按钮时, 在当前页中打开一个新的URL地址。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title><script src="../script/jquery-1.11.1.js"></script><script src="../script/underscore.js"></script><script src="../script/backbone.js"></script></head><body><div id="divShow"></div><input id="btnreload" type="button" value="重载" onclick="window.location.reload();"/><input id="btnreplace" type="button" value="替换" onclick="window.location.replace('http://www.baidu.com');"/></body><script type="text/javascript">var $HTML = "";var $obj_wl = window.location;for(var idx in $obj_wl){$HTML += "<b>" + idx + ":" + "</b>" + $obj_wl[idx] + "</br>";}$("#divShow").html($HTML);</script></html>

2.源码分析

    在本示例的JavaScript代码中,为了将遍历后的location对象各属性名称和值显示在页面元素中,首先定义一个名为$HTML的变量,用于保存内容,然后定义一个名为“$obj_wl”的变量,用于保存location对象。接下来使用for语句遍历location对象,并获取对象的每个属性名称和对应属性值,将他们保存在$HTML中。最后将变量$HTML的内容显示在页面元素中。

    在本示例的页面代码中,添加两个按钮元素时就已绑定onclick事件。单击“重载”按钮时,将调用location对象的reload方法重载当前页;单击“替换”按钮时,将调用location对象的replace方法,在当前页面中打开新页面。

    location对象中的reload和replace方法虽然都是在当前页面重新加载,但两者有本质的区别。前者是重新加载当前页的URL地址,即进行当前页的刷新;后者是先将当前页的URL地址进行替换,再在当前页中加载替换后的URL地址。

    此外,location对象中的hash属性十分重要,该属性易于设置和获取,广泛用于单页应用中局部效果的收藏,可以根据获取的值执行不同的JavaScript代码,实现在单页应用中无刷新变换页面的功能。该属性也应用于下一节将要重点介绍的Backbone框架的导航器(router)中。


7.2 绑定导航地址

    通过前面章节的学习,使我们掌握了浏览器(window)中history、location对象属性和方法的使用。在Backbone框架中构建router类时,大量封装了这两个对象中的属性和方法,将页面特定的url或hash属性与定义好的action或event相绑定。在地址栏浏览这些URL时,触发绑定的action对应的函数或执行相应的事件,可以实现无刷新加载新内容,以及收藏特定URL片段的功能,接下来详细介绍该功能的实现过程。

7.2.1 action方式绑定URL地址

    所谓action方式,是将页面特定的url或hash属性与一个对应的函数(动作)相绑定,即在构建router类时,通过添加routes属性,在该属性中声明url或hash属性和函数的对应关系,这样就完成了两者间的绑定。一旦绑定完成,在浏览器中浏览对应的URL地址时,执行对应函数中的代码。接下来通过一个完整的示例进行介绍。

              示例 7-4 action方式绑定URL地址

1.功能描述 

    在页面中添加两个<div>元素,第一个元素用于创建导航条,在该元素中添加多个超级链接<a>元素。单击某个链接时,进入相应的URL地址。同时在第二个<div>元素中显示对应的功能说明和传回的参数值。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title><script src="../script/jquery-1.11.1.js"></script><script src="../script/underscore.js"></script><script src="../script/backbone.js"></script></head><body><div><a href="">首页</a> |<a href="#search">查询列表</a> |<a href="#search/abc">关键字查询</a> |<a href="#search/abc/p2">页码关键字查询</a> |<a href="#error">其他页</a> |</div><div id="divShow"></div></body><script type="text/javascript">var $divShow = $("#divShow");var testrouter = Backbone.Router.extend({routes:{"":"main","search":"search_list","search/:key":"search_key","search/:key/p:page":"search_key_page","*search":"search_default"},main:function(){$divShow.html("首页");},search_list:function(){$divShow.html("查询列表");},search_key:function(key){$divShow.html("查询关键字为"+key+"记录");},search_key_page:function(key,page){$divShow.html("查询关键字为"+key+"记录,页码为"+page);},search_default:function(){$divShow.html("其他页");}});var router = new testrouter();Backbone.history.start();</script></html>

2.源码分析

    在本示例的JavaScript代码中,首先定义一个名为“$divShow”的变量,用于保存显示内容的页面元素。在构建router模块时添加routes属性,并在该属性值中声明需要监听的URL地址列表。以key/value的形式声明,key表示URL地址中hash属性的规则,而value则表示当在浏览器地址栏中执行该规则声明的URL时,需要执行的动作(action)函数名。

    然后,编写URL地址中hash属性规则执行的函数。在执行函数过程中,可以获取URL地址中hash属性规则传来的实参值,并将该值显示在页面指定的元素中。

    最后,由于URL地址中hash属性的导航功能是由router和history类共同完成的。前者用于声明和解析导航规则,并绑定对应的动作(action)函数名,后者用于监听已绑定的URL地址变化,并触发已绑定的动作(action)。因此,需要先实例化一个router类的对象router,然后通过调用history对象中的start方法启动对URL地址变化的监听。



0 0
原创粉丝点击