ajax实现浏览器前进后退-location.hash与模拟iframe

为什么80%的码农都做不了架构师?>>>   hot3.png

Aajx实现无数据刷新时,我们会遇到浏览器前进后退失效的问题以及URL不友好的问题。

实现方式有两种

1、支持onhashchange事件的,通过更新和读取location.hash的方式来实现

/*

  因为Javascript对dom的操作是不持久化的,刷新后就恢复原状,而且也不保存历史记录,也就无法前进后退来查看历史了。但是可以采用“地址栏加hash”技术来解决。
       地址栏中敲入“页面地址#aaa”就表示跳转到“页面地址 ”的“aaa”这个页内锚点(英文叫做hash)。只要改变“aaa”这个锚点内容,浏览器就认为URL变化,也就会放入浏览历史,这样前进后退问题就解决了。我们只要把不同的AJAX状态通过不同的hash写到地址栏就可以了,当页面加载的时候检测是否有hash值,有的话就读取hash进行相应的ajax还原操作。
       location.hash可以取到或者设置hash的值,当hash改变的时候window.onhashchange事件会被触发,但是页面加载的时候哪怕有hash值,onhashchange事件也不会触发,因此需要在onload事件中也读取hash进行同样的处理,保证刷新页面也能恢复ajax的页面显示。
      下面是例子代码,为了简单的突出问题,这里没有使用ajax,只是通过dom来修改页面状态。点击文本框,文本框的内容会加1(注意观察地址栏),刷新页面后值也还是增加后的值,而且页面可以前进后退。
代码如下:
[html]
<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 
    <title>TestDemo</title> 
    <script src="jquery-1.4.2-min.js"></script> 
    <script type="text/javascript"> 
        var processHash = function () { 
            var hashStr = location.hash.replace("#", ""); 
            if (hashStr) $("#txt1").val(hashStr); 
        } 
        $(function () { 
            $("#txt1").click(function () { 
                var i = parseInt($("#txt1").val()); 
                i++; 
                $("#txt1").text(i); 
                location.hash = "#" + i; 
            }); 
            window.onload = processHash; 
            window.onhashchange = processHash; 
        }); 
    </script> 
</head> 
<body> 
    <input type="text" id="txt1" value="1" /> 
</body> 
</html>

*/

2、通过内嵌一个iframe来模拟实现页面的前进后退,通过iframe的onload事件来实现

/*

我可应很负责任的告诉你:ajax加载页面是无法实现浏览器前进和后退功能的, 因为你是直接通过jq 将当前页面的内容全给替换掉了,而页面并没有跳转。 不过不是所有事都是绝对的。告诉你一个比较笨但是有比较实用的方法。 就是通过iframe轻松解决问题。 首先,你的页面需要一个隐藏的iframe,且iframe的src对应的是一个任意的html,jsp都行。 当你ajax加载页面之前,用jq将当前的页面内容给加载到iframe中去,这个时候,你的iframe中的html元素,就是你当前页面的html元素没错把?这时候再加载你需要ajax加载的页面。注意,加载页面的时候千万不要把这个iframe给覆盖掉了。。。 再写一个键盘后退按键的js监控方法,当按下backspace的时候,将iframe的页面元素加载出来覆盖当前页面,在覆盖之前记得要把现在的页面元素覆盖到iframe中,因为你还有一个前进的操作 前进的操作也是大同小异,说白了就是父页面元素与iframe中的页面元素进行对换的操作

*/


具体代码如下,里面内嵌到的各个页面,自己建立同名文件即可。


<!DOCTYPE html>

<html>

<head>

<title></title>

<meta charset="utf-8">

<style type="text/css">

.tab {

  display: inline;

}

.tab a {

    color: #fff;

    background: #333;

    padding: 5px 10px;

    border-left: 1px solid #fff;

}

.tab .selected {

    color: red;

    background: #cecece;

}

.content {

    background: #cecece;

    width: 50%;

    margin-top: 5px;

    padding: 10px;

}

pre {

  border: 1px inset gray;

  height: 20em;

}

</style>

</head>


<body >


<script type="text/javascript">


function Ajax (params) {


  if (params) {

      this.XMLHttp = params.XMLHttp; 

      this.method = params.method;

  }

  this.onsuccess = null;

  this.responseType = 'text';


}



Ajax.prototype = {

    getXMLHttp : function () {

        if (!this.XMLHttp) {

             if (window.XMLHttpRequest) {

                // code for IE7+, Firefox, Chrome, Opera, Safari

                  return new XMLHttpRequest();

              } else {// code for IE6, IE5

                  return new ActiveXObject("Microsoft.XMLHTTP");

              }

        }

        return this.XMLHttp;

    },


    request : function (url, data) {

        var self = this;

        try {

            var http = this.getXMLHttp();

            //make a connection to the server ... specifying that you intend to make a GET request 

            //to the server. Specifiy the page name and the URL parameters to send


            var param = '';


            for (var item in data) {

                param += (item + '=' + data[item] + '&');

            }

            url += ( (url.indexOf('?') != -1) ? '&' : '?' ) + param;


            var urlLen = url.length;

            if (url.substr(urlLen - 1, urlLen) == '&') {

                url = url.substr(0, urlLen - 1);

            }


            http.open(this.method, url);

            //assign a handler for the response

            http.onreadystatechange = function() {

                self.response(http);

            }

            //actually send the request to the server

            http.send(null);


        } catch (e) {

            alert(e.message);

        }

    },

    

    get : function (url, data, type, onsuccess) {

        this.method = 'GET';

        this.responseType = type || this.responseType;

        this.onsuccess = onsuccess;

        this.request(url, data);

    },


    post : function (url, data, type, onsuccess) {

        this.method = 'POST';

        this.responseType = type || this.responseType;

        this.onsuccess = onsuccess;

        this.request(url, data);

    },


    response : function(http) {

        if (http.readyState == 4) {

            // 4 = "loaded"

            if (http.status == 200) {

            // 200 = OK

                this.onloadDone(http);

            } else {

                this.onerror('加载失败');

            }

        }

    },


    onloadDone : function(http) {

        // var data = http.responseText || http.responseXML;

        var data = this.responseType.toLowerCase() == 'xml' ? http.responseXML : http.responseText;

        this.onsuccess.call(this, data);

    },


    onerror : function (message) {

      alert("Problem retrieving XML data");

      if (this.onerror) {

          this.onerror.call(this, message);

      }

    }



}



var Com = {

    isIE6 : (/MSIE 6/.test(navigator.appVersion)),

    hasHashchange : function() {

        if ("onhashchange" in window) {

            return true;

        }

        return false;

    }


};



function PageLoad () {


  this.iframeObj = null;

  this.iframeWin = null;


  this.iframeSrc = this.iframeSrc || 'history.html';

  this.location  = this.location || window.location;


  this.tab = null;

  this.output = null;

  this.tabs = null;


}



PageLoad.prototype = {


    create : function() {

        if (Com.hasHashchange) {

            return;

        }

        if (!this.iframeObj) {

            var ifr = document.createElement_x('iframe');

            ifr.name = 'hashIframe';

            ifr.id   = 'HashIframe';

            ifr.style.display = 'block';

            document.body.appendChild(ifr);

        }


    },


    bindTabEvent : function() {

        var self = this;

        try {

            var tabs = this.tabs;

            for (var i = 0, l = tabs.length; i < l; i++) {

                tabs[i].onclick = function(evt) {

                    var ele = (event.srcElement || event.target || evt.srcElement);

                    var tg = self.toogleTab(ele);

                    return false;

                }

            }

        } catch (e) {

            alert(e);

        } 

    },


    bindHashEvent : function() {

        // bind onhashchange event

        var self = this;

        onhashchange = function() {

            self.pageLoadDone();

        }

    },


    bindIframeEvent : function() {

        var self = this;

        var ifr = self.iframeObj;

        var ifrWind = self.iframeWin;


        if (ifr.attachEvent) {

                ifr.attachEvent('onload', function() {  

                self.iframeLoadDone();

            });

        } else {

              ifr.onload = function() {

                // self.iframeLoadDone.call(this, self);

                self.iframeLoadDone();

            };

        }

    },


    loadDefaultPage : function() {

        var tabname = 'tab1';

        if (Com.hasHashchange) {

            if (this.getHash() == '') {

                // 如果页面hash值为空,则更改hash为初始化的值

                this.setHash(tabname);

            } else {

                // 如果是带hash访问则直接通过hash值回溯页面

                var tab = this.getHash().split('#')[1];

                this.loadDone(tab);

            }

        } else {

            // 如果是不支持onhashchange的浏览器,如ie6等采用iframe

            this.iframeObj.src = this.iframeSrc + '?tab=' + tabname;

        }

        

    },


    init : function() {

        if (!this.iframeObj) {

            this.create();

        }


        this.iframeObj = document.getElementByIdx_x('HashIframe');

        this.iframeWin = window.frames['hashIframe'];


        this.tab = document.getElementByIdx_x('tab');

        this.output = document.getElementByIdx_x('output');

        this.tabs = this.tab.getElementsByTagName_r('a');


        this.bindTabEvent();

        if (Com.hasHashchange) {

            this.bindHashEvent();

        } else {

            this.bindIframeEvent();

        }

        this.loadDefaultPage();

    },


    loadDone : function(tab) {

        if ('string' != typeof tab) {

            return;

        }

        try {

            var idx = tab.substr(3) - 1;

            var tabs = this.tabs;


            var _callBack = function(data) {

                output.innerHTML = data;

            }


            this.getContent(tabs[idx], _callBack);

            this.toggle(tabs[idx]);


           



        } catch (e) {

            alert(e.message);

        }


    }, 


    pageLoadDone : function() {

        var hash = this.getHash();

        tab = hash.split('#')[1];

        this.loadDone(tab);

    },


    iframeLoadDone : function() {

        var hash = this.iframeWin.location.search;

        var tab = hash.split('=')[1];

        this.loadDone(tab);


    },


    toggle : function(ele) {

        var tabs = this.tabs;

        var idx = 0;

        for (var i = 0, l = tabs.length; i < l; i++) {

            if (ele != tabs[i]) {

                tabs[i].className = '';

            } else {

                tabs[i].className = 'selected';

            }

        }

    },


    toogleTab : function (ele) {

        // 更改hash,以便浏览器监听

        if ( !(ele.nodeType == 1) ) {

            return false;

        }

        var tabname = ele.getAttribute('tabname');


        this.setSelectedTab(tabname);

        this.toggle(ele);


        return false;

    },   


    setHash : function(hash) {

          //window.location = 'location.html#tab=tab' + idx;

          // window.location.hash = hash;

          window.location.hash = hash;

    },


    getHash : function() {

          var hash = window.location.hash;

          return hash;

    },


    setSelectedTab : function(tabname) {

          if (Com.hasHashchange) {

              this.setHash(tabname);

          } else {

              this.iframeObj.src = this.iframeSrc + '?tab=' + tabname;

          }

    },


    getContentByTarget : function(evt, callBackFun) {

        this.getContent(evt.srcElement);

    },


    getContent : function(ele, callBackFun) {

        var ajax = new Ajax();

        var output = this.output;


        var _callBack = function(data) {

            if (typeof callBackFun == 'function') {

                callBackFun(data);

            } else {

                // output.innerHTML = data;

            }

        };


        output.innerHTML = 'loading...';


        var url = ele.href + '?t=' + Math.random() * 100;

        var data = { item : ele.href, 'href' : ele.href };

        ajax.get(url, data, 'json' , _callBack );

    }


}



window.onload = function() {

    new PageLoad().init();

}



</script>


<br>

<h1>Ajax浏览器前进后退</h1>


<h4>

本例通过隐藏location hash来实现前进后退,更改location.hash, 然后通过onhashchange事件来监听hash变化,通过hash值来还原页面,不支持onhashchange事件的浏览器如ie6还是需要通过iframe模拟来实现。<a href="location2.html">查看iframe版本</a></h4>



<div class="tab" id="tab">

<a href="data1.txt" tabname="tab1" class="selected">tab1</a><a href="data2.txt" tabname="tab2">tab2</a><a tabname="tab3" href="data3.txt">tab3</a>

</div>

<div class="content">

<pre id="output">

<strong>Loading Ajax接收显示的内容:</strong>

</pre>

</div>


</body>

</html>





转载于:https://my.oschina.net/sheila/blog/384787

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/545159.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java环境变量配置以及遇到的一些问题

java环境变量配置以及遇到的一些问题1_下载2_配置环境变量2.1_配置JAVA_HOME2.2_配置CLASS_PATH2.2_配置系统路径PATH3_遇到的问题3.1_输入java -version无效3.2_javac无效1_下载 2_配置环境变量 打开我的电脑&#xff0c;右击空白处点击属性 点击高级系统设置 点击环境变量…

c fputc 函数重写_使用示例的C语言中的fputc()函数

c fputc 函数重写C中的fputc()函数 (fputc() function in C) Prototype: 原型&#xff1a; int fputc(const char ch, FILE *filename);Parameters: 参数&#xff1a; const char ch, FILE *filenameReturn type: int 返回类型&#xff1a; int Use of function: 使用功能&a…

信息系统状态过程图_操作系统中的增强型过程状态图

信息系统状态过程图The enhanced process state diagram was introduced for maintaining the degree of multiprogramming by the Operating System. The degree of multiprogramming is the maximum number of processes that can be handled by the main memory at a partic…

Java中竟有18种队列?45张图!安排

今天我们来盘点一下Java中的Queue家族&#xff0c;总共涉及到18种Queue。这篇恐怕是市面上最全最细讲解Queue的。本篇主要内容如下&#xff1a;本篇主要内容帮你总结好的阻塞队列&#xff1a;18种Queue总结一、Queue自我介绍 队列原理图1.1 Queue自我介绍hi&#xff0c;大家好&…

肯德尔相关性分析_肯德尔的Tau机器学习相关性

肯德尔相关性分析Before we begin I hope you guys have a basic understanding of Pearson’s and Spearmans correlation. As the name suggests this correlation was named after Maurice Kendall in the year 1938. 在开始之前&#xff0c;我希望你们对皮尔逊和斯皮尔曼的…

40 张图带你搞懂 TCP 和 UDP

我们本篇文章的组织脉络如下运输层位于应用层和网络层之间&#xff0c;是 OSI 分层体系中的第四层&#xff0c;同时也是网络体系结构的重要部分。运输层主要负责网络上的端到端通信。运输层为运行在不同主机上的应用程序之间的通信起着至关重要的作用。下面我们就来一起探讨一下…

腾讯推出高性能 RPC 开发框架

Tars是基于名字服务使用Tars协议的高性能RPC开发框架&#xff0c;同时配套一体化的服务治理平台&#xff0c;帮助个人或者企业快速的以微服务的方式构建自己稳定可靠的分布式应用。Tars是将腾讯内部使用的微服务架构TAF&#xff08;Total Application Framework&#xff09;多年…

看完这篇文章,我再也不怕面试官问「垃圾回收」了...

前言 Java 相比 C/C 最显著的特点便是引入了自动垃圾回收 (下文统一用 GC 指代自动垃圾回收)&#xff0c;它解决了 C/C 最令人头疼的内存管理问题&#xff0c;让程序员专注于程序本身&#xff0c;不用关心内存回收这些恼人的问题&#xff0c;这也是 Java 能大行其道的重要原因之…

react从不会到入门

react从不会到入门1_react初识1.1_react基础环境搭建1.2_文件目录介绍1.2_JSX基础1.2.1_JSX介绍1.2.2_JSX表达式1.2.3_列表渲染1.2.4_条件渲染1.2.5_函数调用1.2.6_样式控制2_组件基础2.1_函数组件2.2_点击事件3_组件通讯3.1_父子关系4_生命周期4.1_挂载阶段4.2_更新阶段5_Hook…

Microsoft Dynamics CRM 数据库连接存储位置在哪里 是在注册表里

Microsoft Dynamics CRM 数据库连接存储位置是在注册表里

Redis的8大数据类型,写的真好

来源 | blog.itzhouq.cn/redis2最近这几天的面试每一场都问到了&#xff0c;但是感觉回答的并不好&#xff0c;还有很多需要梳理的知识点&#xff0c;这里通过几篇 Redis 笔记整个梳理一遍。Redis 的八大数据类型官网可查看命令&#xff1a;http://www.redis.cn/commands.htmlR…

前后端(react+springboot)服务器部署

前后端&#xff08;reactspringboot&#xff09;服务器部署1_前端reactumi服务器部署1.1_前端生成dist目标文件1.2_准备连接服务器的工具1.3_安装nginx1.4_部署项目1.4.1_传输dist文件1.4.2_配置配置文件1.4.3_启动nginx2_后端springboot项目部署服务器2.1_后端生成目标文件2.2…

提高生产力,最全 MyBatisPlus 讲解!

如果你每天还在重复写 CRUD 的 SQL&#xff0c;如果你对这些 SQL 已经不耐烦了&#xff0c;那么你何不花费一些时间来阅读这篇文章&#xff0c;然后对已有的老项目进行改造&#xff0c;必有收获&#xff01;一、MP 是什么MP 全称 Mybatis-Plus &#xff0c;套用官方的解释便是成…

c#象棋程序_C ++程序确定象棋方块的颜色

c#象棋程序A chess board is equally divided into 64 identical squares that are black and white alternately. Each square on the chessboard can be identified by the coordinates as A to H on the horizontal axis and 1 to 8 on the vertical axis as shown in the f…

MySQL中你必须知道的10件事,1.5万字!

攻击性不大&#xff0c;侮辱性极强1、SQL语句执行流程MySQL大体上可分为Server层和存储引擎层两部分。Server层&#xff1a;连接器&#xff1a;TCP握手后服务器来验证登陆用户身份&#xff0c;A用户创建连接后&#xff0c;管理员对A用户权限修改了也不会影响到已经创建的链接权…

Xamarin只言片语2——Xamarin下的web api操作

在很多时候&#xff0c;我们是希望手机app是要和服务端关联&#xff0c;并获取服务端的数据的&#xff0c;本篇博文我们看一下在xmarin下&#xff0c;怎么和用web api的方式与服务端连接并获取数据。首先看web api的开发&#xff0c;本实例是用Visual Studio 2013 with update …

求求你,别再用wait和notify了!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;Condition 是 JDK 1.5 中提供的用来替代 wait 和 notify 的线程通讯方法&#xff0c;那么一定会有人问&#xff1a;为什么不…

一文学搞懂阿里开源的微服务新贵Nacos!

正式开始之前我们先来了解一下什么是 Nacos&#xff1f;Nacos 是阿里的一个开源产品&#xff0c;它是针对微服务架构中的 「服务发现」、「配置管理」、「服务治理」的综合性解决方案。官网给出的回答&#xff1a;“Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组…

The connection to adb is down, and a severe error has occured.

转自&#xff1a;http://blog.csdn.net/yu413854285/article/details/7559333 &#xff08;感谢原文作者&#xff0c;问题解决&#xff09; 启动android模拟器时.有时会报The connection to adb is down, and a severe error has occured.的错误.在网友说在任务管理器上把所有…

线程池的7种创建方式,强烈推荐你用它...

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;根据摩尔定律所说&#xff1a;集成电路上可容纳的晶体管数量每 18 个月翻一番&#xff0c;因此 CPU 上的晶体管数量会越来越…