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…

登陆 tomcat manager

想进去很简单 就在tomcat的配置文件 conf/tomcat-user.xml中加入 <role rolename"manager-gui"/><user username"dev" password"dev" roles"manager-gui"/> /* 而<role rolename"manager-gui"/>是指拥…

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

信息系统状态过程图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;大家好&…

ssh框架常见错误与解决方法

1.Class not Found Exception 异常.---->解决方法&#xff1a;在lib中加入两个jar包&#xff08;spring.jar与struts2- spring-plugin-2.1.8.1.jar&#xff09;&#xff1b;2.使用hql语句时出现java.lang.reflect.InvocationTargetException(即使用hql回调函数带参数时) 或…

使用gzip优化web应用(filter实现)

相关知识&#xff1a; gzip是http协议中使用的一种加密算法,客户端向web服务器端发出了请求后&#xff0c;通常情况下服务器端会将页面文件和其他资源&#xff0c;返回到客户端&#xff0c;客户端加载后渲染呈现&#xff0c;这种情况文件一般都比较大&#xff0c;如果开启Gzip …

肯德尔相关性分析_肯德尔的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;同时也是网络体系结构的重要部分。运输层主要负责网络上的端到端通信。运输层为运行在不同主机上的应用程序之间的通信起着至关重要的作用。下面我们就来一起探讨一下…

android手机两种方式获取IP地址

http://www.cnblogs.com/android100/p/Android-get-ip.html 1.使用WIFI 首先设置用户权限 Xml代码 <uses-permission android:name"android.permission.ACCESS_WIFI_STATE"></uses-permission> <uses-permission android:name"android.permi…

进程、线程、多线程相关总结

进程、线程、多线程相关总结 一、说说概念 1、进程&#xff08;process&#xff09; 狭义定义&#xff1a;进程就是一段程序的执行过程。 广义定义&#xff1a;进程是一个程序关于某个数据集合的一次运行。它是操作系统动态执行的基本单元&#xff0c;在传统的操作系统中&#…

z字扫描和光栅扫描的转换_扫描转换计算机图形中的直线

z字扫描和光栅扫描的转换扫描转换直线 (Scan Converting a Straight Line) For the scan conversion of a straight line, we need the two endpoints. In normal life, if we want to draw a line we simply draw it by using a scale or ruler. But we cant draw a line on t…

TextView 单行显示长文本

android:singleLine"true"//单行显示 android:ellipsize"end"//省略号出现在末尾 http://blog.csdn.net/wxg630815/article/details/8996091

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

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

Failed connect to github.com:443; No error

任务目标&#xff1a;将线上已有的https://github.com/eyjian/mooon.git克隆到本地的E:\GitHub\mooon目录问题描述&#xff1a;使用Git的Windows客户端UI工具GitHub执行克隆操作时报错&#xff0c;查看它的日志&#xff0c;难发现问题&#xff0c;于是改用Git的Windows命令行终…

python 程序耗时记录_Python学校的学生身高记录程序

python 程序耗时记录A team of 5 people is assigned with a task to record the heights of students in a school and they have decided to make a python program using class to record all the students height. 由5人组成的小组负责记录学校中学生的身高&#xff0c;他…

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

前言 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…

Windows系统端口转发

1、添加端口转发 netsh interface portproxy add v4tov4 listenport10001 listenaddress192.168.1.100 connectport10001 connectaddress192.168.1.105 2、删除端口转发 netsh interface portproxy del v4tov4 listenport10001 listenaddress192.168.1.100 3、查看已存在的端口…

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

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