`

使用ajax和window.history.pushState无刷新改变页面内容和地址栏URL

    博客分类:
  • JS
 
阅读更多
后退时关闭当前页面
<script type="text/javascript">
jQuery(document).ready(function ($) {
        if (window.history && window.history.pushState) {
            $(window).on('popstate', function () {
      WeixinJSBridge.call('closeWindow');
      /**
      window.opener=null;
          window.open('','_self');
          window.close();
      */
            return false;
            });
            window.history.pushState('forward', null, 'Wx.AuthSuccess.jdp');
  //  window.history.pushState('forward', null, 'baidu.com');
  //window.location.href="www.baidu.com";

  //WeixinJSBridge.call('closeWindow');
        }
    });
</script>



2、替换当前历史记录点

window.history.replaceState和window.history.pushState类似,不同之处在于replaceState不会在window.history里新增历史记录点,其效果类似于window.location.replace(url),都是不会在历史记录点里新增一个记录点的。当你为了响应用户的某些操作,而要更新当前历史记录条目的状态对象或URL时,使用replaceState()方法会特别合适。

3、监听历史记录点

监听历史记录点,直观的可认为是监听URL的变化,但会忽略URL的hash部分,监听URL的hash部分,HTML5有新的API为onhashchange,我的博客里也有说到该方法和跨浏览器的兼容解决方案。可以通过window.onpopstate来监听url的变化,并且可以获取存储在该历史记录点的状态对象,也就是上文说到的json对象,如:

// 当前的url为:http://www.qingdou.me/post-1.html
window.onpopstate=function()
{
// 获得存储在该历史记录点的json对象
var json=window.history.state;
// 点击一次回退到:http://www.qingdou.me/index.html
// 获得的json为null
// 再点击一次前进到:http://www.qingdou.me/post-1.html
// 获得json为{time:1369647895656}
}
值得注意的是:javascript脚本执行window.history.pushState和window.history.replaceState不会触发onpopstate事件。

还有一点注意的是,谷歌浏览器和火狐浏览器在页面第一次打开的反应是不同的,谷歌浏览器奇怪的是回触发onpopstate事件,而火狐浏览器则不会。


======================================================================
QA team通过Tealeaf 和Avicode检测到application有很多的500 errrors,因此这2周几乎都在解决这个问题。通过reproduce这些各种不同的错误,几乎可以把原因归结在浏览器的后退按钮(pressing back button)和键盘的后退键 (backspace),和leader交流下,觉得有必要阻止页面后退。

当然,相关的文章到处走势,其实就是一篇文章都是转来转去的.基本上是3个solution:

1).设置网页过期(服务器端)

2).javascript:window.history(客户端)

3).对于键盘的backspace.通过window.event来过滤,当然要考虑的是对于Input控件,要保持删除的功能。

<script type="text/javascript">

function backspace() {

if (event.keyCode == 8 && event.srcElement.tagName != "INPUT" && event.srcElement.type != "text")

            event.returnValue = false;

     }

if (navigator.appName == "Microsoft Internet Explorer") {

         window.history.forward(1);

     }

else // if it is Mozilla than

     {

         window.history.forward(-1);

     }   

</script>

下面是我的尝试:

1) 先来说对于,网页过期的:

网页一旦过期,意味着每次页面的刷新,需要重新从服务器端获取所有的网页资源。这时候如果通过浏览器的后退按钮,进行后退,就会reload整个页面,相当于一个get request.因此对于相应页面会执行 OnLoad事件,以及OnLoadCompleted事件

若在OnLoadCompleted事件页面没能获取到所需要的资源,将会显示网页已过期的错误。但是无论讲*****怎样添加到页面中,都不能重现网页已过期的错误,

2) 对于页面可客户端的OnLoad执行脚本: Windows.History.Forward(1),对于这个方法别人说不完美,但没有说处理理由。我相说的是,对于直接点击后腿按钮的情况,Window.History.Forward(1)几乎可以Cover 大多数场景,只是一个奇怪的事情当所有的后退经过一个页面的时候,就会停止,不会继续forward 到原来页面。原以为这就是我们的解决500 errors的钥匙,但是一次不经意的聊天,让我们想起了,如果不是点击后腿按钮,而是选择HIstory List中网页,又该如何去处理? 为了解决这一问题,我有2个想法

a)获取选择HistoryList中页面的index,然后Windows.History.Froward(index), 查阅资料,最后在msdn上看到的解释是,处于安全的因素microsoft 不会暴露Window.history对象中url 实际地址和Index,也就是说无法得到HistoryList 网页的具体信息。

b)  记录后退之前页面的URL,然后直接用Windows.Location.Href,记录后退之前的url这个不难,<%= %> <%#%>, 均可做到,但是问题来了,如何区分网页的get reque是由于后退造成的,似乎有一个无解!

不过在探索a,b 的时候,想到2个问题

1)关于Windows..history.forward();如果windows.history List中只有5个页面,但是我把Windows..history.forward(100),结果会是如何。

2)如果我在history list选择一个距离当前页面距离不是1的页面 Windows..history.forward(1),会如何工作?

解释:

   1)其实Windows..history.forward(100)和Windows..history.forward(1)的效果是一样的.

   那Windows..history.forward(1),究竟是如何工作的,通过http watch

wps_clip_image-11801

可以看到,Windows..history.forward(1),总是会将windows.history.list里买你的所有页面走完,直到页面再也不能往前,对于windows.history.list.length=5的时候,无论在哪个页面发起history,forward(1),都会走到当前页面。因此是可以很好地阻止页面后退,缺点是带来了很多的额外的http request,因为需要一个页面一个页面后退。

另外一个奇怪的问题:在我们的一个application里面我发现,windows.history.forward(1),会走到某个页面,停止。以至于在那个页面之后的页面,就无法实现组织后退的功能。我偶然发现对于windows.history.forward(1)页面居然会执行OnInit ,Onload ,OnloadComplete这些事件,我很费解,为什么windows.history.forward会触发服务器端事件呢,然来是因为在基类里面设置了缓存过期,这样每次需要从server上取页面资源 。

因此页面过期和windows.history.forward是不可以一起使用的

===============================================================


     按微信产品部副总经理张颖“每一个公众号都是一个APP”的说法,我们确实可以利用微信内置浏览器访问为公众号设计WebApp单页应用,以使得客户在访问公众号时有近似原生App的体验,不过目前这样的公众号很少,原因除了使用javascript开发单页应用的难度比开发一般的Web页面难度更高一些,更重要的一点是使用微信内置浏览器访问Web页面时,Android用户一按物理返回键就回到微信界面,而Android用户按物理返回键的习惯预期是回到上一页,这样就使得微信公众号的WebApp客户体验非常差。

  有什么方法改变这一点么?最理想的解决办法是微信自己接管用户按物理返回键这个事件,然后类似像getNetworkType一样提供javascript事件给开发者使用。不过很遗憾,腾讯目前没有提供这个事件,而且看样子将来也不打算提供。

  这个问题不是大问题,但如果不解决会影响Android用户的客户体验。幸运的是,我找到了解决办法,方法就是利用javascript window history来解决。

  由于安全原因javascript不允许修改history里已有的url链接,但可以使用pushState方法往history里增加url链接,并且提供popstate事件监测从history栈里弹出url。我们可以利用这一点,在WebApp加载主界面后先往history里压入“#”链接,然后监听popstate事件,在Android手机的浏览器,按下物理返回键默认的操作是执行window.history.back(),此时将触发popstate事件。收到popstate事件时代码显示“再按一次退出程序”div顶层标签,此时history栈已经为空,如用户再次按下物理返回键将执行默认操作回到微信。接着,我们要设定一个定时器,在指定的时间(比如2秒)后如用户没有再次按下物理返回键将再次往history里压入“#”链接,并隐藏“再按一次退出程序”div顶层标签,等待用户下一次按下物理返回键。


pushHistory();

setTimeout(function () {

  window.addEventListener("popstate", function(e) {

    showBox("再按一次退出程序", 2000, function() {      

      pushHistory();

    });

  }, false);
08
}, 300);



function pushHistory() {

  var state = {

    title: "title",

    url: "#"

  };

  window.history.pushState(state, "title", "#");

}



function showBox(msg, timeOut, onTimeOut) {

  if (typeof alertBoxDiv === "undefined") {

    alertBoxDiv = $("<div/>").addClass("alert-box hide").append( $("<div/>").addClass("label label-primary")).appendTo($("body"));

  }

  alertBoxDiv.children(".label").html(msg);

  alertBoxDiv.removeClass("hide");

  if (typeof timeOut === "undefined") timeOut = 2000;

  setTimeout(function() {

    alertBoxDiv.addClass("hide");

    if (typeof onTimeOut !== "undefined") onTimeOut();

  }, timeOut);

}


  监听popstate事件的代码稍作修改就可以用于任意控制单页应用中javascript生成的任意动态页面的跳转,此方法已经在微信公众号WebApp中使用,可在微信中搜索“myfunds”公众号关注体验。这个方法也可以用于微信公众号之外的WebApp,链接就不发了,免得CSDN又要审查。




window.history.pushState('forward', null, 'Wx.deputyDiaryList.jdp?t='+new Date().getTime());
1.在一个页面中添加多少历史记录,后退,只要没有页面的转换,就不会跳转到页面;(A--B页面。再B页面pushState 多少记录,后退时 这些记录URL都不会刷新该URL的页面;只有在B到A的时候才会触发)

2.
微信中 只要按后退键就触发$(window).on('popstate', function () {};



浏览器中:
流程是:A->B,B原URL--新增一个新URL显示在地址栏--当按后退按钮时地址栏先退回原URL--
--退回A最后的RUL,这时才会触发  $(window).on('popstate', function () {}。


history.replaceState

流程是:A->B,B原URL--替换一个新URL显示在地址栏--当后退时则直接退回新URL地址页面
(好像)并不触发$(window).on('popstate', function () {};
可能是因为地址栏地址都一样导致。。


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics