实现不刷新整个页面进行前进后退

在html5出来前,实现无刷新前进后退通常是结合location.hash+onhashchange事件来实现的;
在html5出来后,可以使用h5 history api来实现无刷新前进后退

点击浏览器的前进后退按钮时,只要将要进入的页面与当前页面不是同一个页面(因为有可能人为地添加了一条历史记录,但实际上还是同一个页面),那么将要进入的页面其所有请求(包括html、js、css、json和图片等)都是直接从缓存里读取的(除非禁用了缓存),但js还是会重新执行一遍。如果该页面是用ajax获取数据的,那么不管前进或者后退到该页面时,都会重新ajax请求数据。


HTML5中history那些事
SEPTEMBER 26TH, 2015
HTML5中History对象提供了两个新的方法,pushState和replaceState用来在无刷新页面情况下更改url,为单页应用提供了很大方便,但是在使用时需要注意一些事情。

原来有什么
History对象原来有三个方法,一个属性。

history.length:历史列表中的网址数。
history.back():加载历史列表前一个网址。
history.forward():加载历史列表后一个网址。
history.go(num):加载历史列表中的某个页面,参数为相对当前页面,跳转的次数。go(-1)与back()效果相同,go(1)与forward()效果相同。go(-2)与单击两次后退按钮执行的操作一样。
新增了什么
History对象新增了两个方法,一个属性,新增了一个事件。

history.pushState(state,title,url):替换url为当前url并添加历史记录,title为历史记录的title,state为一个用户存储的对象,可以通过history.state或window.onpopstate事件的event.state访问。
history.replaceState(state,title,url):参数与history.pushState相同,不同点在于该方法更改当前历史记录,不会产生新的历史记录。
history.state:用户存储的对象。
window.onpopstate:当使用history.pushState或history.replaceState控制历史记录后,触发浏览器的前进/回退操作会触发该事件。
注意事项
state属性不能通过history.state或window.onpopstate的event.state来修改,只能通过history.pushState或history.replaceState修改。
state属性必须是可序列化的值,如DOM对象不可设置。
history.state与window.onpopstate的event.state不相等。
history.pushState与history.replaceState的url参数与网站url必须是同域的,否则会出现跨域错误。需要注意,当history.pushState或history.replaceState的url参数为/abc/def或abc/def时所使用的origin为加载该<script>的origin,如果操作History的是外部js文件,请拼接上location.origin。

还差什么
当前在哪
History没有提供获取当前页面在历史列表位置的方法,这个属性作用不大,只有在单页应用,且拥有非顺序跳转逻辑时才会用到,既然系统不提供,只能自己推算。
首先要保证每个页面设置state属性,这样可以通过该属性判断是否是已经加载过页面。 当首次加载应用时,检查history.state属性,如果该属性未设置,那么必然为新开页面,此时必然为历史列表第一个,当使用history.pushState后,逻辑同上。,此两种情况current为history.length。其余情况即为页面跳转或当前页面刷新,current即为之之前两种情况保存的值。


HTML4中的History API
属性
length 历史的项数。javascript 所能管到的历史被限制在用浏览器的“前进”“后退”键可以去到的范围。本属性返回的是“前进”和“后退”两个按键之下包含的地址数的和。
方法
back() 后退,跟按下“后退”键是等效的。
forward() 前进,跟按下“前进”键是等效的。
go() 用法:history.go(x);在历史的范围内去到指定的一个地址。如果 x < 0,则后退 x 个地址,如果 x > 0,则前进 x 个地址,如果 x == 0,则刷新现在打开的网页。history.go(0) 跟 location.reload() 是等效的。

HTML5中的History API(使用h5的history api可以不用更改页面url的hash值)

操纵浏览器的历史记录
  1. history.pushState(data, title [, url]):往历史记录堆栈顶部添加一条记录;data会在onpopstate事件触发时作为参数传递过去;title为页面标题,当前所有浏览器都会 忽略此参数;url为页面地址,可选,缺省为当前页地址。
  2. history.replaceState(data, title [, url]) :更改当前的历史记录,参数同上。
  3. history.state:获取历史栈中最顶端的state数据(即history.pushState中的第一个参数),不同浏览器的读写权限不一样。
  4. popstate事件:当用户单击浏览器的 后退或者前进 按钮(或者调用history.go,history.back,history.forward方法也会触发popstate事件。调用history.pushState()或者history.replaceState()不会触发popstate事件,但改变url中的hash值会触发popstate事件)时触发该事件。在事件处理函数中读取触发事件的事件对象的state属性值,该属性值即为执行pushState方法时所使用的第一个参数值,该state与history.state是相同的,而不是历史栈中被抛出的state对象。
到目前为止,IE10,firefox4以上的版本,Chrome8以上的版本,Safari5,Opera11以上的版本浏览器支持HTML5中的History API。

判断是否支持h5 history api:
if ('pushState' in history) { ... };

h5 history api实现无刷新跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!DOCTYPE html>
<html lang= "en" >
<!-- saved from url=(0014)about:internet -->
<head>
     <meta charset= "UTF-8" >
     <title></title>
</head>
<body>
<a href= "" >change color</a>
<p style= "cursor:pointer;text-decoration:underline;" >other color</p>
<div style= "height: 100px;background-color: red;" ></div>
<script>
     history.replaceState({
         color:  'red'
     },  '红色' 'red.html' );
     window.onpopstate =  function  (event) {
         setBackgroundColor(event.state.color);
     };
     document.getElementsByTagName( 'a' )[0].onclick =  function  (event) {
         event.preventDefault();
         if  (history.state.color ===  'red' ) {    //上一次为红色
             setBackgroundColor( 'green' );
             history.pushState({
                 color:  'green'
             },  '绿色' 'green.html' );
         else  if  (history.state.color ===  'green'  || history.state.color ===  'yellow' ) {   //上一次为绿色或黄色
             setBackgroundColor( 'blue' );
             history.pushState({
                 color:  'blue'
             },  '蓝色' 'blue.html' );
         }
     };
document.getElementsByTagName( 'p' )[0].onclick= function (event){
    if  (history.state.color !==  'yellow' ) {    //如果当前页不是黄色
setBackgroundColor( 'yellow' );
             history.pushState({
                 color:  'yellow'
             },  '黄色' 'yellow.html' );   
}
}
     function  setBackgroundColor(color) {
         document.getElementsByTagName( 'div' )[0].style.backgroundColor = color;
     }
</script>
</body>
</html>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!DOCTYPE html>
<html lang= "en" >
<head>
     <meta charset= "UTF-8" >
     <title>history 测试</title>
</head>
<body>
     
     <p><input type= "text"  value= "0"  id= "oTxt"  /></p>
     <p><input type= "button"  value= "+"   id= "oBtn"  /></p>
 
     <script>
 
     var  otxt = document.getElementById( "oTxt" );
     var  oBtn = document.getElementById( "oBtn" );
     var  n = 0;
 
     oBtn.addEventListener( "click" , function (){
         n++;
         add();
     }, false )
     get();
 
     function  add(){
         if ( "pushState"  in  history){
             otxt.value=n;
             history.pushState({num:n}, null ,location.href.split( "?" )[0]+ "?num=" +n);
         }
     }
     function  get(){
         if ( "onpopstate"  in  window){
             window.addEventListener( "popstate" , function (e){
                 alert( 'popstate事件' );
                 if (e.state && e.state.num){
                     n = e.state.num;
                 } else {
                     n=0;
                 }
                 otxt.value = n;
             }, false );
         }
     }
     
     </script>
</body>
</html>

使用location.hash+onhashchange实现无刷新跳转

原理:改变url中#后面的值会创建一条历史记录(但不会刷新整个页面)并会触发onhashchange事件。监听此事件并通过window.location.hash获取url中 "#val" 的值。根据不同的"#val" 来触发页面不同的操作,显示对应内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html>
<html lang= "en" >
<head>
     <meta charset= "UTF-8" >
     <title>history 测试</title>
</head>
<body>
 
<p><input type= "text"  value= "0"  id= "oTxt"  /></p>
<p><input type= "button"  value= "+"   id= "oBtn"  /></p>
 
<script>
     var  otxt = document.getElementById( "oTxt" );
     var  oBtn = document.getElementById( "oBtn" );
     var  n = 0;
 
     oBtn.addEventListener( "click" , function (){
         n++;
         add();
     }, false );
     get();
 
     function  add(){
         if ( "onhashchange"  in  window){
             window.location.hash =  "#" +n;
         }
     }
 
     function  get(){
         if ( "onhashchange"  in  window){
             window.addEventListener( "hashchange" , function (e){
                 var  hashVal = window.location.hash.substring(1);
                 if (hashVal){
                     n = hashVal;
                 } else {
                     n=0;
                 }
                 otxt.value = n;
             }, false );
         }
     }
</script>
</body>
</html>


JS刷新页面

1,reload 方法,该方法强迫浏览器刷新当前页面。
语法:location.reload([bForceGet])   
参数: bForceGet, 可选参数, 默认为 false,从客户端缓存里取当前页。true, 则以 GET 方式,从服务端取最新的页面, 相当于客户端点击 F5("刷新")

2,replace 方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,你不能通过“前进”和“后退”来访问已经被替换的URL。
语法: location.replace(URL)   
通常使用: location.reload() 或者是 history.go(0) 来做。
此方法类似客户端点F5刷新页面,所以页面method="post"时,会出现"网页过期"的提示。
因为Session的安全保护机制。
当调用 location.reload() 方法时, aspx页面此时在服务端内存里已经存在, 因此必定是 IsPostback 的。
如果有这种应用: 需要重新加载该页面,也就是说期望页面能够在服务端重新被创建,期望是 Not IsPostback 的。
这里,location.replace() 就可以完成此任务。被replace的页面每次都在服务端重新生成。
代码: location.replace(location.href);

返回并刷新页面:
location.replace(document.referrer);
document.referrer //打开当前页面的文档的URL
这种方法并不是返回到上一个历史记录,而是将当前的记录替换为document.referrer,导致history中有重复的两个document.referrer记录
不要用 history.go(-1),或 history.back();来返回并刷新页面,这两种方法不会刷新页面,而是直接从浏览器缓存里获取内容(除非禁用了缓存)。


Javascript刷新页面(即重新从服务器下载页面)的几种方法:


F5和CTRL+F5的区别
以下都是在chrome下测试的

1,history.go(0) 
跟按F5一样,无法跳过浏览器缓存。F5触发的 所有HTTP请求 的请求头中通常包含了If-Modified-Since 或 If-None-Match字段,或者两者兼有.如果服务器认为被请求的文件没有发生变化,则返回304响应,浏览器直接从缓存中获取.
注意点:上述情况只适用于第一次请求时响应头中携带Last-Modified或者ETag字段的请求,如果第一次请求时响应头中没有携带这些字段,而是携带的Transfer-Encoding:chunked(分块传输),那么再次发起该请求时,请求头里不会携带If-Modified-Since 或 If-None-Match字段,会从服务器重新下载文件

CTRL+F5触发的HTTP请求的请求头中没有上面的那两个头 (所有的请求都是从服务器重新获取数据) ,却有Pragma: no-cache 或 Cache-Control: no-cache 字段,或者两者兼有.服务器看到no-cache这样的值就会把最新的文件响应过去.也就跳过了缓存.

2,location.reload() 
3,location=location 
4,location.assign(location) 
5,document.execCommand('Refresh') 
6,window.navigate(location) 
7,location.replace(location) 

8,document.URL=location.href


来源网址:http://www.qdfuns.com/notes/17631/ff37e5968e6592847e05c14ce754c917.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值