window.location.hash屬性介紹

window.location.hash屬性介紹javascript

location是javascript裏邊管理地址欄的內置對象,好比location.href就管理頁面的url,用location.href=url就能夠直接將頁面重定向url。而location.hash則能夠用來獲取或設置頁面的標籤值。好比http://domain/#admin的location.hash="#admin"。利用這個屬性值能夠作一個很是有意義的事情。php

不少人都喜歡收藏網頁,以便於之後的瀏覽。不過對於Ajax頁面來講的話,通常用一個頁面來處理全部的事務,也就是說,若是你瀏覽到一個Ajax頁面裏邊有意思的內容,想將它收藏起來,但是地址只有一個呀,下次你打開這個地址,仍是得像以往同樣不斷地去點擊網頁,找到你鍾情的那個頁面。另外的話,瀏覽器上的「前進」「後退」按鈕也會失效,這於不少習慣了傳統頁面的用戶來講,是一個很大的使用障礙。html

那麼,怎麼用location.hash來解決這兩個問題呢?其實一點也不神祕。前端

好比,個人做者管理系統,主要功能有三個:普通搜索、高級搜索、後臺管理,我分別給它們分配一個hash值:#search、#advsearch、#admin,在頁面初始化的時候,經過window.location.hash來判斷用戶須要訪問的頁面,而後經過javascript來調整顯示頁面。好比:java

var hash; jquery

hash=(!window.location.hash)?"#search":window.location.hash; git

window.location.hash=hash; github

  //調整地址欄地址,使前進、後退按鈕能使用 ajax

switch(hash){   chrome

case "#search":  

    selectPanel("pnlSearch");   //顯示普通搜索面板  

    break;    

case "#advsearch":    

      

case "#admin":  

     

}

經過window.location.hash=hash這個語句來調整地址欄的地址,使得瀏覽器裏邊的「前進」、「後退」按鈕能正常使用(實質上欺騙了瀏覽器)。而後再根據hash值的不一樣來顯示不一樣的面板(用戶能夠收藏對應的面板了),這就使得Ajax頁面的瀏覽趨於傳統化了。

 

 

用HTML5來控制瀏覽器地址欄,並支持前進和後退

 

如今單頁無刷新應用裏,即用Ajax獲取數據,經過前端JS渲染頁面,用戶在一個頁面裏完成幾乎全部的事情。爲了讓瀏覽器記住並標示出當前所處的頁面,須要用錨點,即location.hash來記錄參數。由於直接修改location.href的話會形成頁面跳轉。下面介紹的方法是HTML5新增長的方法,能夠自由的控制瀏覽器歷史記錄,使得地址欄真正改變而不是各類#。

 

 

如下爲轉載:

原文地址:

{

'第一段': 'http://note.sdo.com/u/1185659399/n/6GXE7~jE5sx0LX0xI000pW',

'第二段': 'http://hi.baidu.com/kooboy/blog/item/6f2c31adadedc2134b36d691.html',

'文檔': 'https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history'

}

 

第一段

1. 問題是什麼?

 

可能未寫過 Ajax 應用的人會好奇,改變 URL 而且支持後退是這麼難的事麼?這在現階段確實是個難題。產生問題的地方主要有兩點。

1.1 改變當前 URL 會讓瀏覽器載入頁面

 

Javascript 有一個函數能夠改變當前 URL 路徑。

window.location = '/' 

若是在瀏覽器的網頁調試程序(firebug 或 chrome 原生調試工具)的控制檯輸入這行代碼,頁面會立刻跳轉到當前網站的根目錄。這跟用戶點擊了一個超連接的效果同樣。

而若是隻改變 URL 的 # 號後面部分,不會致使瀏覽器從新載入網頁。由於瀏覽器認爲 # 號是當前頁面的一個錨點,也就不須要刷新了。

window.location = '#here' // 不會致使頁面刷新 

稍後還會利用到這個特性。

1.2 瀏覽器不懂得記錄 Ajax 調用的狀態

 

由於 Ajax 調用是多種多樣的,統計代碼會引起 Ajax,廣告會引起 Ajax,頁面定時刷新會引起 Ajax,因此瀏覽器並不知道如何記錄 Ajax 的狀態。

若是用戶點擊一個連接經過 Ajax 刷新了頁面,而後進入其餘頁面,再而後點了返回按鈕,會產生什麼情況呢?瀏覽器會把上次 Ajax 調用返回的數據原封不動的傾倒出來,這多是 javascript 代碼,多是未處理的 json 數據。一個成熟的網站不會出現這樣的狀況,由於開發人員已經用各類方法作了處理(後面討論)。不過你如何在兩天前的晚上訪問 codecampo.com,有可能會看到這種狀況,由於那時候我還不懂怎麼處理。: )

1.3 目標

 

理想中應該讓 Ajax 調用達到這樣的狀態:

若是 Ajax 調用後的頁面邏輯上已經跟以前不是同一個頁面,那麼 URL 應該隨之改變。

前提同上,那麼在新頁面點擊瀏覽器的後退按鈕,應該回到 Ajax 調用前的頁面。

狀態 1 是爲了讓訪客能夠將當前網頁放入收藏夾,或者經過複製粘貼 URL 分享資源地址;狀態 2 是爲了符合最小驚訝。

2. 當前主流 - 只改變 URL Hash 的單頁面應用

 

仔細觀察能夠發現,如今的 Twitter,Google,Facebook 的 URL 地址充斥着 #號或者 #! 號。例如一個新版 Twitter 地址是這樣的

https://twitter.com/#!/chloerei 

這個 #! 號有什麼意義呢?這個能夠看看阮一峯整理的這篇《URL的井號》。這裏假設你已經瞭解 # 號後面的改變不會致使頁面加載,怎麼利用這個特性達到 1.3 提出的目標。

2.1 第一步,有關 Ajax 調用的連接所有用 #path 做爲連接目標

 

例如,若是一個連接原本是

<a href="/topics/1">topic1</a> 

就修改成

<a href="#/topics/1">topic1</a> 

顯然,若是不作後續工做的話,這個連接點擊後頁面不會發生什麼變化,用戶也不會被帶到新地址。惟一的改變是 URL 的 # 號部分變成了 #topics/1

2.2 設置 onhashchange 事件

 

在 javascript api 中,窗口 window 對象的 hash 值(# 號後面部分)發生變化時,會調用 onhashchange 事件。給 onhashchange 掛上一個 function,就能夠在 hash 有改動的時候調用這個 function。

例如能夠在控制檯輸入這段 js 代碼測試

window.onhashchange = function(){alert(window.location.hash)}

實際中 function 裏面就是放置真正用來刷新頁面的代碼了。好比在 jQuery 裏用 $.get(location.path)。

2.3 效果

 

如今的 twitter,gooogle,facebook 都是使用這種方法刷新頁面,這對瀏覽器書籤、後退的支持也很好。

可是這有一些反作用。

一是由於頁面路徑被寫在了 Hash 裏面,而瀏覽器是不向服務器發送 Hash 部分的。因此打開這樣的 URL 須要兩個來回:一、打開空白的首頁 二、根據 Hash 用 Ajax 載入實際內容

二是把路徑寫在了 Hash 裏面破壞了 URL 原先的含義。從 URL 字面看

https://twitter.com/#!/chloerei 

這個頁面表示的是 twitter.com 頁面上的 !/chloerie 錨點。但從實際內容上,這表示的是 chloerei 的我的頁面。因此有人稱這種站點爲「單頁面應用」。總的來講,這個方案對主流瀏覽器的支持程度很高,是目前的主流方案。

3. 將來方案:基於 history.pushState API

 

先看現實中的例子:Github。Github 的源碼瀏覽頁面是藉助 Ajax,而且正常改變 URL 的例子,瀏覽器後退功能也正常工做。你能夠在 https://github.com/chloerei/campo 點擊各個文件夾,同時觀察地址欄。不過目前只支持對 HTML5 友好的瀏覽器,好比 chrome, firefox4。

Github 有篇簡短的日誌描述了他們的實現方法:https://github.com/blog/760-the-tree-slider

下面再逐步分析一下。

3.1 改變 URL 但不載入頁面的方法

 

HTML5 中新增了 history.pushState 方法,用以向瀏覽器添加歷史記錄,可是不觸發頁面載入。詳細的文檔能夠看這裏。

基本用法就是在 Ajax 發送的同時,將訪問的地址用 pushState 方法加入頁面歷史。若是你用 Rails 的 ujs-jquery 方式調用 Ajax,看起來是這樣的(campo項目的部分代碼)

HTML 部分

<div class="paginate"><a href="/?page=1" data-remote="true">下一頁</a></div> 

data-remote 屬性是 ujs 用來啓用 ajax 的標誌位。

js 部分

$('.paginate a').live('ajax:beforeSend', function(event, xhr, settings) {   if (history && history.pushState) {

    history.pushState(null, document.title, this.href);

  }

});

這個鉤子方法,在發送 ajax 請求以前把目標地址推動瀏覽器的歷史記錄,因而瀏覽器的地址欄更新但不重載整個頁面。

3.2 處理後退按鈕

 

瀏覽器後退的時候會觸發 onpopstate 事件,因此要給這個事件掛上處理方法。

if (history && history.pushState) {

  $(window).bind("popstate", function() {     $.getScript(location.href);

  });

}

這裏的邏輯跟URL Hash 的單頁面應用的方法很相似,不一樣的是以前處理的是 hashchange,這裏處理的是 popstate。

3.3 從非 Ajax 頁面返回到 Ajax 頁面

 

作完上面兩步,已經能夠在 Ajax 頁面來回切換了,可是若是進入了一個非 Ajax 頁面,而後按了後退,這時候就會把以前 Ajax 獲取的代碼所有倒出來,由於上下文已經切換了,瀏覽器不知道怎麼處理這些代碼。

這時候要作兩個處理

1)要求 Ajax 相關頁面不緩存,若是你用 Rails,你能夠看這篇文章: http://blog.serendeputy.com/posts/how-to-prevent-browsers-from-caching-a-page-in-rails/

2)處理 popstate 的方法增長一個標誌位,第一次載入頁面的時候不要調用後面的邏輯。

if (history && history.pushState) {

  var loaded = false;

  $(window).bind("popstate", function() {     if (!loaded) {

      loaded = true;

    } else {

      $.getScript(location.href);

    }

  });

}

注意 loaded 這個變量的做用。由於以前已經把頁面緩存關了,若是不設置這個標誌位,瀏覽器後退的時候就會既載入頁面,也觸發 popstate 事件,致使二次載入。

 

 

第二段

history.pushState/replaceState 方法

 

熟悉JavaScript開發的同窗,對History確定不會陌生,其中最經典的方法就是go,經過第一個類型爲整數的傳輸參數,可使瀏覽器到達當前頁面以前或以後,曾經瀏覽過的頁面。固然,這個也是要刷新來實現的。

如今History API新增了兩個方法,分別是pushState和replaceState,其實用法都同樣,看Mozilla的文檔也沒看到它們有多大不一樣,哈哈。

用法以下:

var state = { //這裏能夠是你想給瀏覽器的一個State對象,爲後面的StateEvent作準備。

title : "HTML 5 History API simple demo",

url : "yourpage"

};

history.pushState(state, "HTML 5 History API simple demo", "yourpage");

還算簡單吧,那麼replaceState也是一樣的用法:

var state = { //這裏能夠是你想給瀏覽器的一個State對象,爲後面的StateEvent作準備。

title : "HTML 5 History API simple demo",

url : "yourpage"

};

history.replaceState(state, "HTML 5 History API simple demo", "yourpage");

State Event

既然有無刷新改變URL的方法,固然也要有響應這個改變的時間啦。

嗯,沒錯。就有一個popstate事件,而傳入的handler函數有一個參數,就是以前在pushState的第一個參數,一個State obj。開發者能夠經過這個State obj來識別行爲。詳細代碼以下:

var state = { //這裏能夠是你想給瀏覽器的一個State對象,爲後面的StateEvent作準備。

title : "HTML 5 History API simple demo",

url : "yourpage"

};

history.pushState(state, "HTML 5 History API simple demo", "yourpage");

window.onpopstate = function (e) { document.title = e.state.title;}

固然還能夠這樣:

var state = { //這裏能夠是你想給瀏覽器的一個State對象,爲後面的StateEvent作準備。

action : "page",

title : "HTML 5 History API simple demo",

url : "yourpage"

};

history.pushState(state, "HTML 5 History API simple demo", "yourpage");

window.onpopstate = function (e) {

switch (e.state.action) {

case "home" :

document.title = "HOME ……";

$.get("index.php").done(function (data) { 

$("#wrapper").html(data); 

});

break;

case "page" :

document.title = e.state.title;

$.get(e.state.url).done(function (data) { 

$("#wrapper").html(data); 

});

break;

}

相關文章
相關標籤/搜索