• 谈谈HTML5中的history.pushSate方法,弥补ajax导致浏览器前进后退无效的问题


    移动端为了减少页面请求,有时候需要通过单页面做成多页面的效果,最近有这么个需求,表单填完后执行第一步,然后执行第二步,第二步执行完后再执行第三步,每一步都要保留之前的数据。这种情况用单页面实现再合适不过了。

    一般都是通过修改URL的hash,然后通过监听hashchange来达到模拟切换页面的效果。搞定之后,客户端也就是高大上的IOS开发工程师说获取不到webview的history,擦,hashchange明明会产生浏览器的history,怎么会获取不到,哥之前一直都这么做的,也没有客户端的说获取不到啊,是你自己不知道怎么获取吧....当然,这话是在心里说的。他还把这事给经理说了....我去,然后我就知道了还有HTML5中pushstate这么个玩意。

    先回顾下window.history吧。

    History 对象

    History 对象包含用户(在浏览器窗口中)访问过的 URL。

    History 对象是 window 对象的一部分,可通过 window.history 属性对其进行访问。

    注释:没有应用于 History 对象的公开标准,不过所有浏览器都支持该对象。

    History 对象属性

    length:返回浏览器历史列表中的 URL 数量。

    History 对象方法

    back():加载 history 列表中的前一个 URL。即后退

    forward():加载 history 列表中的下一个 URL。即前进

    go():加载 history 列表中的某个具体页面。这个是最常用的

    History 对象最初设计来表示窗口的浏览历史。但出于隐私方面的原因,History 对象不再允许脚本访问已经访问过的实际 URL。

    咱们来接着说两个HTML5 history新增的好哥们:History.pushState()History.replaceState()

    history.pushState(state, title, url)

    意思就是把一个history记录插入到历史记录中。

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

    title:页面标题。

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

    history.replaceState(state, title, url)

    用新的state和URL替换当前。不会造成页面刷新。

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

    title:页面标题。

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

    window.onpopstate

    history.go和history.back(包括用户按浏览器历史前进后退按钮)触发,并且页面无刷的时候(由于使用pushState修改了history)会触发popstate事件,事件发生时浏览器会从history中取出URL和对应的state对象替换当前的URL和history.state。通过event.state也可以获取history.state。

    大致的思路就是自己创建一个对象记录,然后把它插入到浏览器的历史记录,点击浏览器的前进后退按钮会触发onpopstate,然后判断当前的记录做对应的操作。

    与传统的AJAX的区别

    传统的ajax有如下的问题:

    虽然ajax可以无刷新改变页面内容,但无法改变页面URL

    其次为了更好的可访问性,内容发生改变后,改变URL的hash。但是hash的方式不能很好的处理浏览器的前进、后退等问题 

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

    再有,ajax的使用对搜索引擎很不友好,往往蜘蛛爬到的区域是空的

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

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

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

    注意事项:

    1、onpopstate只有在点击浏览器的前期和后退才会触发;

    2、pushState能够改变浏览器地址栏中的hash,但是它不会触发hashchange事件,所以想通过监听hashchange来执行是无效的。

    3、pushState不会刷新页面,刷新页面咱就压根不会用它了。

    本地一个简单实例

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>pushState</title>
        <style type="text/css">
        .hidden {
            display: none;
        }
        </style>
        <script type="text/javascript" src="zepto.min.js"></script>
    </head>
    
    <body>
        <section id="step1" class="step-contain" step="1">
            <p>第1步</p>
            <button class="step-btn" step="1">下一步</button>
        </section>
        <section id="step2" class="step-contain hidden" step="2">
            <p>第2步</p>
            <button class="step-btn" step="2">下一步</button>
        </section>
        <section id="step3" class="step-contain hidden" step="3">
            <p>第3步</p>
        </section>
        <script type="text/javascript">
        $(function() {
            stepProgress();
    
            function stepProgress() {
                var options = {
                    curStep: 1,
                    nextStep: null
                }
                var defaultState={
                    "step": options.curStep,
                     "url": "#step=" + options.curStep
                }
                window.history.pushState(defaultState, "", defaultState.url);
                $(".step-btn").on("click", function() {
                    var step = parseInt($(this).attr("step"));
                    options.nextStep = step + 1;
                    var state = {
                        "step": options.nextStep,
                        "url": "#step=" + options.nextStep
                    }
                    window.history.pushState(state, "", state.url);
                    console.log(state.step)
                    swapStaus(options.nextStep);
                });
    
                function swapStaus(step) {
                    $(".step-contain").each(function() {
                        var tmpStep = $(this).attr("step");
                        if (parseInt(tmpStep) == step) {
                            $("#step" + tmpStep).removeClass("hidden");
                        } else {
                            $("#step" + tmpStep).addClass("hidden");
                        }
                    });
                    options.curStep = step;
                }
    
                $(window).on("popstate",function(){
                    var currentState = history.state;
                    goStep=currentState.step?currentState.step:1;
                    swapStaus(goStep)
                })
            }
    
        })
        </script>
    </body>
    
    </html>
  • 相关阅读:
    华为云文字识别服务关键技术、能力和产品落地需要注意的事宜(OCR系列二)
    【华为云技术分享】大数据容器化,头部玩家尝到了甜头
    【华为云技术分享】9 个Java 异常处理的规则!
    【华为云技术分享】一统江湖大前端DOClever—你的Postman有点Low
    【华为云技术分享】大前端的自动化工厂— babel
    非编程人学Python,要注意哪些隐秘的错误认知?
    【华为云技术分享】【一统江湖的大前端】PPT制作库impress.js
    【鲲鹏来了】鲲鹏迁移过程案例分享
    【华为云技术分享】圣诞特别版 | 数据库频频出现OOM问题该如何化解?
    HBuilder开发App
  • 原文地址:https://www.cnblogs.com/hutuzhu/p/4535234.html
Copyright © 2020-2023  润新知