历史返回,若无页面则跳转到指定页面

开头总要有点废话html

 

这个功能在原先的js分享中 有简单的带过,这里拎出来 详细的讲解下原理和存在的问题(因为是运用html5的新API 因此有兼容问题,推荐移动端使用该方法)。html5

功能描述:算法

在浏览器中新建标签页并指定一个网址,网页加载完毕后,正常流程下是不容许点击返回的。由于当前标签页的相关历史记录是没有的,因此没有记录能够返回。浏览器

应客户要求,须要在这种状况下,给他的历史记录里添加一个连接(好比首页),这样在新打开的页面,点击返回就能够跳转到首页,让用户看到系统的各类功能,推广平台。安全

 

 

知识要点微信

 

HTML5引进了history.pushState()方法和history.replaceState()方法,它们容许你逐条地添加和修改历史记录条目。这些方法能够协同window.onpopstate事件一块儿工做。session

 

案例

假设 http://mozilla.org/foo.html 将执行以下JavaScript代码:优化

1 var stateObj = { foo: "bar" }; history.pushState(stateObj, "page 2", "bar.html");

 

这将让浏览器的地址栏显示http://mozilla.org/bar.html,但不会加载bar.html页面也不会检查bar.html是否存在。google

假设如今用户导航到了http://google.com,而后点击了后退按钮,此时,地址栏将会显示http://mozilla.org/bar.html,而且页面会触发popstate事件,该事件中的状态对象(state object)包含stateObj的一个拷贝。该页面看起来像foo.html,尽管页面内容可能在popstate事件中被修改。url

若是咱们再次点击后退按钮,URL将变回http://mozilla.org/foo.html  文档将触发另外一个popstate事件,此次的状态对象为null。回退一样不会改变文档内容。

pushState()方法

pushState()有三个参数:一个状态对象、一个标题(如今会被忽略),一个可选的URL地址。下面来单独考察这三个参数的细节:

  • 状态对象(state object) — 一个JavaScript对象,与用pushState()方法建立的新历史记录条目关联。不管什么时候用户导航到新建立的状态,popstate事件都会被触发,而且事件对象的state属性都包含历史记录条目的状态对象的拷贝。

    任何可序列化的对象均可以被当作状态对象。由于FireFox浏览器会把状态对象保存到用户的硬盘,这样它们就能在用户重启浏览器以后被还原,咱们强行限制状态对象的大小为640k。若是你向pushState()方法传递了一个超过该限额的状态对象,该方法会抛出异常。若是你须要存储很大的数据,建议使用sessionStorage或localStorage。

  • 标题(title) — FireFox浏览器目前会忽略该参数,虽然之后可能会用上。考虑到将来可能会对该方法进行修改,传一个空字符串会比较安全。或者,你也能够传入一个简短的标题,标明将要进入的状态。

  • 地址(URL) — 新的历史记录条目的地址。浏览器不会在调用pushState()方法后加载该地址,但以后,可能会试图加载,例如用户重启浏览器。新的URL不必定是绝对路径;若是是相对路径,它将以当前URL为基准;传入的URL与当前URL应该是同源的,不然,pushState()会抛出异常。该参数是可选的;不指定的话则为文档当前URL。

注意: 在 Gecko 2.0 (Firefox 4 / Thunderbird 3.3 / SeaMonkey 2.1) 至 Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2) 中,传入的对象使用JSON来进行序列化。从 Gecko 6.0 (Firefox 6.0 / Thunderbird 6.0 / SeaMonkey 2.3)开始,对象使用 结构化拷贝算法来进行序列化。这将容许更多类型的对象可以安全传入。

某种意义上,调用pushState()有点相似于设置window.location='#foo',它们都会在当前文档内建立和激活新的历史记录条目。但pushState()有本身的优点:

  • 新的URL能够是任意的同源URL,与此相反,使用window.location方法时,只有仅修改 hash 才能保证停留在相同的document中。

  • 根据我的须要来决定是否修改URL。相反,设置window.location='#foo',只有在当前hash值不是foo时才建立一条新历史记录。

  • 你能够在新的历史记录条目中添加抽象数据。若是使用基于hash的方法,你只能把相关数据转码成一个很短的字符串。

注意pushState()方法永远不会触发hashchange事件,即使新的地址只变动了hash。

popstate事件

每当激活的历史记录发生变化时,都会触发popstate事件。若是被激活的历史记录条目是由pushState所建立,或是被replaceState方法影响到的,popstate事件的状态属性将包含历史记录的状态对象的一个拷贝。

replaceState()方法

history.replaceState()操做相似于history.pushState(),不一样之处在于replaceState()方法会修改当前历史记录条目而并不是建立新的条目。

当你为了响应用户的某些操做,而要更新当前历史记录条目的状态对象或URL时,使用replaceState()方法会特别合适。

 

实现思路

1.利用popstate事件,监听点击返回事件。

2.触发事件时,判断当前页面的历史记录 是否有页面能够返回。

3.若是没有页面能够返回,则插入两条记录:

一、指定的跳转页面。

二、空记录。(使当前页面不发生变化)

 

实现方法

    //返回以前没页面则返回首页
        function pushHistory() {
            if (history.length < 2) {
                var state = {
                    title: "index",
                    url: getHttpPrefix + "index.html"
                };
                window.history.pushState(state, "index", location.href);
                state = {
                    title: "index",
                    url: ""
                };
                window.history.pushState(state, "index", "");
            }
            //lll("history.state" + history.state)
            //console.log(history.state)  
        }

 

判断当前history中的记录个数,因为页面加载的时候,浏览器会自动push进一个记录。因此要判断长度是否小于2.

塞进的state对象是为了获取对应的url连接。
注意点:
第一个pushState我将跳转url放进state对象 方便跳转操做。第二个参数没有实际意义,由于如今的浏览器基本不适用这个参数。

第三个参数是会替换当前地址栏的连接的,可是页面不会发生跳转。(我以前犯了个错误,将第三个参数设置为首页连接,致使了地址栏更改成首页连接,以致于在当前页的连接 都以首页为基础进行跳转,致使页面的全部连接都跳转错误了。)

    setTimeout(function () {
            pushHistory()
            window.addEventListener("popstate", function (e) {
                lll("popstate"+window.history.state)
                if (window.history.state != null && window.history.state.url != "") {
                    location.href = window.history.state.url
                }
            });
        }, 300);

 

这段代码放置在页面的ready事件中执行,延迟300毫秒是为了将操做滞后,防止与系统pop事件冲突。
if语句为了判断 history是否存在state对象,由于只有知足咱们要求的记录才会有咱们添加的state对象 因此 根据这点能够进行页面的跳转操做。
这样就能够实现咱们想要的效果。
 

写在最后

缺点:
     1. 很明显,就如开头提到的。只适合支持html5的浏览器使用。
     2.因为插进了两条记录 ,因此 相似于 微信这种移动端的返回,须要再点击两次返回,才能推出页面,回到微信聊天窗口,用户体验很差。
总结:
这种方法 必定还能够优化和完善,只是目前个人实力不足,还不足以完善到完美的程度。
但愿看到这篇文章的朋友能够提出本身的看法,意见!
相关文章
相关标签/搜索