解决Ajax框架下页面回退刷新问题

http://blog.csdn.net/u010403387/article/details/45576055

存在问题

如果使用Firefox等浏览器访问RMS网站时,我们可能会发现页面之间的切换是通过AJAX异步请求实现的,同时页面的URL不会发生改变,虽然可以通过页面上的按钮通过AJAX异步请求实现回退刷新,但是对于浏览器前进和后退不能支持,每当刷新与后退之后,页面都会退到最开始的欢迎页面。AJAX可以实现页面的局部刷新,可以做到非常好的数据加载效果,给用户带来非常良好的体验,但是AJAX不能在浏览器的历史会话中保留记录,当你点开一个页面,AJAX各种数据加载非常快捷,例如一个列表页面可以用异步加载来翻页,但是如果用户一不小心刷新了页面,那么页码就得重新开始计算,一旦用户改变了会话状态(浏览器的前进、后退、刷新),那么AJAX就会丢失相关的数据。



传统的AJAX存在如下的问题:

1、可以无刷新改变页面内容,但无法改变页面URL

2、不能支持通过网址直接访问系统某一模块,必须进过点按操作

3、回退、刷新必须开发人员自己第一,既给开发人员增加了工作量,又不符合用户习惯

4、进而浏览器引入了onhashchange的接口,不支持的浏览器只能定时去判断hash是否改变

5、但这种方式对搜索引擎很不友好



使用技术

为了解决传统ajax带来的问题,HTML5里引入了新的API,即:history.pushState,history.replaceState

可以通过pushStatereplaceState接口操作浏览器历史,并且改变当前页面的URL

pushState是将指定的URL添加到浏览器历史里,replaceState是将指定的URL替换当前的URL

history.pushState(state, title, url)

将当前URLhistory.state加入到history中,并把新的stateURL添加到当前。不会造成页面刷新。

state:与要跳转到的URL对应的状态信息。

title:标题(现在是被忽略,未作处理)

url:要跳转到的URL地址,不能跨域。

history.replaceState(state, title, url)

history.replaceState()操作类似于history.pushState(),不同之处在于replaceState()方法会修改当前历史记录条目而并非创建新的条目。

state:与要跳转到的URL对应的状态信息。

title:标题(现在是被忽略,未作处理)

url:要跳转到的URL地址,不能跨域。



addEventListener(type, listener)

addEventListener是一个侦听事件并处理相应的函数。

type:事件的类型。

listener:侦听到事件后处理事件的函数。此函数必须接受 Event对象作为其唯一的参数,并且不能返回任何结果。



解决方法



由于AJAX无刷新改变页面内容的,所以页面的URL始终是不变的,为了区分页面上的各个不同内容,首先需要重新定义一下各个页面的URL,因为RMS网站多使用$.post异步请求,我们可以用URL记录post请求的各个参数(请求地址、传递参数),当浏览器进行刷新、回退操作时,根据URL记录的信息自动发送post请求,进入对应页面,从而实现希望的功能。



定义URL语法:

已如下地址为例:“http://localhost/rms_hold/index.php/Home/Index/loadHomePage#/rms_hold/index.php/Home/ResourceRequest/getRequestPage@apply_type=1&resource_name=ADM_BIZCARD!1



“http://localhost/rms_hold/index.php/Home/Index/loadHomePage”是原先页面的URL,如果在问题解决之前在RMS网站上进行任何点按操作,网址一直不会有任何变动。现在我们使用“#”分割网址,“#”之后就是我们所记录的ajax请求“/rms_hold/index.php/Home/ResourceRequest/getRequestPage是请求的地址,它由“#”与“@”分割,而在“@”与“!”之间的这是发向请求地址的各个参数,“apply_type=1与“resource_name=ADM_BIZCARD由“&”进行分割。



刷新、回退监听处理:

[html]  view plain copy
  1. if (history.pushState) {  
  2.   
  3. window.addEventListener("popstate", function() {  
  4.   
  5. back_ajax_mod_url();  
  6.   
  7. back_ajax_post();  
  8.   
  9. if(location.href.indexOf("#")==-1){  
  10.   
  11. window.location.reload();  
  12.   
  13. }  
  14.   
  15. });  
  16.   
  17. back_ajax_mod_url();  
  18.   
  19. back_ajax_post();  
  20.   
  21. }  




如以上代码所示,window对象上提供了onpopstate事件,可以使用addEventListener方法监听onpopstate事件,每当URL因为浏览器回退时都会对得到的URLback_ajax_mod_url()back_ajax_post()函数中进行解析、处理,而当浏览器刷新时,根据history.pushState的返回值不空,依然会对得到的URLback_ajax_mod_url()back_ajax_post()函数中进行解析、处理。



对外接口:



[html]  view plain copy
  1. function back_ajax_mod_url(){  
  2.   
  3. var url_ajax=ajaxback_url.pop();  
  4.   
  5. var title ="Home | UniqueSoft RMS";  
  6.   
  7. if(url_ajax){  
  8.   
  9. history.pushState({ title: title }, title,location.href.split("#")[0] + "#"+ url_ajax);  
  10.   
  11. }  
  12.   
  13. }  



介绍一下back_ajax_mod_url()函数,它与数组ajaxback_url组成对外接口,ajaxback_url是一个全局数组,用来存放需要加入到history中的URL,然后由back_ajax_mod_url()函数在无页面刷新的情况下将当前URLhistory.state加入到history中。



[html]  view plain copy
  1. $("#reportTable tbody").on("click", "trtd img[alt = 'Detail']",  
  2.   
  3. function() {  
  4.   
  5. var id = $(this).attr("business_leave_id");  
  6.   
  7. $.post("__MODULE__/ReportCenter/getReportDetailPage",{  
  8.   
  9. "report_name": "ADM_TRAVEL_REP",  
  10.   
  11. "item_id": id,  
  12.   
  13. },  
  14.   
  15. function(data) {  
  16.   
  17. ajaxback_url.push("__MODULE__/ReportCenter/getReportDetailPage"+ "@" + "item_id=" + id + "&" +"report_name=ADM_TRAVEL_REP");  
  18.   
  19. $("#container").html(data);  
  20.   
  21. back_ajax_mod_url();  
  22.   
  23. });  
  24.   
  25. });  




以上函数是RMS系统里的一个AJAX异步请求事件,会造成页面无刷新变化,加粗部分就是我们提供的对外接口,使用该接口后在history中会产生一条新的URL用来记录达到该页面的post方法。



URL解析处理器:



如下面函数所示back_ajax_post()RMS系统的URL解析处理器,根据之前提到的URL语法,读出页面上改变内容的AJAX请求,并且自动发送AJAX请求,获取需要的页面

[html]  view plain copy
  1. function back_ajax_post() {  
  2.   
  3. if (location.href.indexOf("#")!= -1) {  
  4.   
  5. var post_href =location.href.split("#")[1];  
  6.   
  7. if (location.href.indexOf("@")!= -1) {  
  8.   
  9. var post_url =post_href.split("@")[0];  
  10.   
  11. var post_params =post_href.split("@")[1];  
  12.   
  13. if(post_params.indexOf("!") != -1) {  
  14.   
  15. var post_page_index =post_params.split("!")[1];  
  16.   
  17. post_params =post_params.split("!")[0];  
  18.   
  19. };  
  20.   
  21. } else {  
  22.   
  23. var post_url = post_href;  
  24.   
  25. var post_params = "";  
  26.   
  27. var post_page_index = "";  
  28.   
  29. }  
  30.   
  31. var get_resource_href =location.href;  
  32.   
  33. if(get_resource_href.indexOf("!") != -1) {  
  34.   
  35. get_resource_href =get_resource_href.split("!")[0];  
  36.   
  37. };  
  38.   
  39. if(get_resource_href.indexOf("resource_name=") != -1) {  
  40.   
  41. var has_resource_name =get_resource_href.split("resource_name=")[1];  
  42.   
  43. var siderbar_index =has_resource_name;  
  44.   
  45. } else if(get_resource_href.indexOf("report_name=") != -1) {  
  46.   
  47. var has_resource_name =get_resource_href.split("report_name=")[1];  
  48.   
  49. var siderbar_index =has_resource_name.split("_REP")[0];  
  50.   
  51. };  
  52.   
  53. if (!post_page_index ||$("#personalInfo").length <= 0) {  
  54.   
  55. if (!post_url) {  
  56.   
  57. window.location.href ="__MODULE__";  
  58.   
  59. }  
  60.   
  61. $.ajax({  
  62.   
  63. type: "post",  
  64.   
  65. url: post_url,  
  66.   
  67. data: post_params,  
  68.   
  69. success: function(res){  
  70.   
  71. $('#pageContainer').html(res);  
  72.   
  73. if(post_page_index) {  
  74.   
  75. location.hreflocation.href.split("!")[0] + "!1";  
  76.   
  77. } else {  
  78.   
  79. location.hreflocation.href.split("!")[0];  
  80.   
  81. };  
  82.   
  83. },  
  84.   
  85. error: function(res) {  
  86.   
  87. window.location.href = "__MODULE__";  
  88.   
  89. },  
  90.   
  91. });  
  92.   
  93. }  
  94.   
  95. //for request page next&back  
  96.   
  97. if (post_page_index) {  
  98.   
  99. var previous_index =$(".navbar,.steps .navbar-innerul.row-fluid").find("li.active").find(".number").text();  
  100.   
  101. var differ =post_page_index - previous_index;  
  102.   
  103. lock_for_req_back_next =1;  
  104.   
  105. if (differ > 0) {  
  106.   
  107. for (var i = 0; i <differ; i++) {  
  108.   
  109. $("#personalInfo").trigger("click");  
  110.   
  111. };  
  112.   
  113. } else {  
  114.   
  115. differ = -differ;  
  116.   
  117. for (var i = 0; i <differ; i++) {  
  118.   
  119. $("#btn_back").trigger("click");  
  120.   
  121. };  
  122.   
  123. };  
  124.   
  125. lock_for_req_back_next =0;  
  126.   
  127. }  
  128.   
  129. //for side bar  
  130.   
  131. if (siderbar_index =="IT_TESTMACHINE" || siderbar_index == "IT_LAPTOP"|| siderbar_index == "IT_OTHER_RESOURCE") {  
  132.   
  133. siderbar_index ="IT_RESOURCE";  
  134.   
  135. }  
  136.   
  137. $("ul.page-sidebar-menuli ul.sub-menu li a").each(function() {  
  138.   
  139. var resource_name =$(this).attr("href").split("resource_name=")[1];  
  140.   
  141. if (siderbar_index ==resource_name) {  
  142.   
  143. $('.page-sidebarul').children('li.active').removeClass('active');  
  144.   
  145. $('.page-sidebarul').children('arrow.open').removeClass('open');  
  146.   
  147. $(this).parents('li').each(function() {  
  148.   
  149. $(this).addClass('active');  
  150.   
  151. $(this).children('a > span.arrow').addClass('open');  
  152.   
  153. $(this).parents('.sub-menu').show();  
  154.   
  155. });  
  156.   
  157. $(this).parent('li').parents('li').addClass('active open');  
  158.   
  159. return false;  
  160.   
  161. } else {  
  162.   
  163. $('.sub-menu').hide();  
  164.   
  165. }  
  166.   
  167. });  
  168.   
  169. $("ul.page-sidebar-menuli").not(".open").find("ul").hide();  
  170.   
  171. }  
  172.   
  173. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值