2012-02-18 44 views

回答

25

location.hashhistory.pushState方法有更好的支持。
pushState方法的優點是可以將狀態綁定到歷史記錄條目。
如果您不需要此狀態對象,我建議使用location.hash屬性,以便與舊版瀏覽器具有更好的兼容性。

location.hash = 'new-hash'; 
console.log(history.state); // null or undefined 

history.pushState({extraData: "some state info"}, '', 'new-hash'); //<--- 
console.log(history.state); // [object Object] = {"extraData": "some state info"} 
+0

但是有可能爲history.state添加書籤或將其發佈到Facebook上?我認爲這可能與哈希。他們是完全不同的東西。 – Robert 2012-07-15 00:19:57

+0

@Robert當您收藏某些內容時,會使用當前在瀏覽器中看到的URL。狀態對象與歷史記錄條目相關聯。而且,只有當瀏覽歷史記錄(例如瀏覽器關閉後的會話恢復)導航到頁面時纔可用。一種方法不排除另一種方法:使用'history.pushState'('從服務器緩存的一些長狀態','','/ posts/id#prefix-some-specific-identifier')'是合法的,例如,如果應用程序確實需要它。在這個例子中,服務器響應被緩存。順便說一句,哈希也可能是斜線。 – 2012-07-15 08:29:57

+1

啊,當然。所以你的回答真的讓它失望了。''hash'有更好的支持,'pushState'更強大。 – Robert 2012-07-16 01:54:02

13

history.pushState要好於location.hash。但它是一個HTML5功能。所以最好有一個像下面這樣的回退方法。

if (typeof(window.history.pushState) == 'function') { 
    window.history.pushState(null, path, path); 
} else { 
    window.location.hash = '#!' + path; 
} 
+1

自問題出現3年後,現在哪個更好,pushstate或location.hash? – hous 2015-11-19 16:54:47

22

Pushstate是未來。這是因爲:

  1. 它看起來更乾淨。
  2. 在重溫深層鏈接時,您實際上可以展示真實的服務器端數據,以支持諸如SEO和Facebook Open Graph(都會發送蜘蛛來抓取頁面的html)等內容。
  3. 服務器無權訪問散列標籤數據,因此您無法在服務器日誌中看到它,所以它可以幫助一些分析人員。
  4. 它有助於修復哈希標記問題。例如,我有一個Nginx重寫,將訪問我的應用的用戶重定向到相同的https網址。它適用於所有的瀏覽器,但Safari會將你重定向到沒有散列的域名(如此令人討厭)!
  5. 實際上,您可以使用散列標籤來表示深層鏈接到長頁面的部分。
  6. 您可以使用真實的HTTP後端請求來支持不支持推送狀態的瀏覽器,或者您可以退回到使用哈希標記。兩者都需要額外的實施,但只需一點工作即可輕鬆完成。

見從GitHub的設計師這次談話的更多:http://warpspire.com/talks/responsive/

+1

Pushstate雖然有一個小缺點:它會強制服務器在首次訪問時/當您在新選項卡中打開鏈接頁時爲您呈現頁面。如果一個人打開了10個標籤頁(說,瀏覽一個圖庫並打開有趣的圖片),它比hashbangs慢得多,因爲ajax根本不用。 – 2014-06-02 14:51:14

+1

@ Hello-World:這是一個假設。對於許多/大多數基於JavaScript的框架,它正在做與hashbangs完全相同的事情。 – 2014-06-25 06:02:57

+0

你能解釋一下嗎?假設我訪問example.com/ajax#gallery,我的瀏覽器通過example.com/ajax下載了一些js,然後js請求並呈現#gallery。當我在新選項卡中打開example.com/ajax#image1時,我的瀏覽器已經緩存了example.com/ajax,因此它只需要獲取#image1並進行渲染即可。據我所知,Pushstate並不是這種情況。當您在新選項卡中打開example.com/ajax/image1(pushstate)或第一次訪問它時,無論example.com/ajax上的緩存如何,瀏覽器都必須下載完整頁面。如果我錯了,我可以改正。 – 2014-06-25 08:11:51

7

我同意其他的答案,但這裏有幾個參數贊成location.hash

  • 它在每瀏覽器,包括Internet Exploder TM
  • history.pushState是一個開發標準,API未來可能會更改
  • 如果用戶在新窗口/選項卡中打開鏈接,散列URL確保沒有加載頁面所需的服務器請求(如果設置了正確的緩存標頭)
  • 服務器配置非常簡單,因爲所有的服務器曾經看到的網址是沒有哈希部分

編輯:我忘了一個

  • 用#標籤,你可以使用真正的鏈接(a href)。因此,您不必設置點擊偵聽器,這可以提高性能並減少代碼大小。
+0

Google會發送#!基於瀏覽器的哈希...需要一點點努力...爲photogallery.classiccars.com做了這個 – Tracker1 2012-07-15 03:27:48

+0

有沒有計劃讓Pushstate更好地使用新的選項卡? – 2014-07-03 09:24:11

+0

變通方法也很受歡迎 – 2014-07-03 09:51:30

7

window.location.hash與HTML5 history.pushstate的優缺點很大程度上取決於您希望頁面的降級程度。

在這裏,你可能會感興趣的優雅降級兩種不同的情況:

第一個是客戶端不支持JavaScript,或者自動機器人/網絡爬蟲訪問您的網站。從SEO角度來看,這一點尤爲重要。如果您的網頁/網頁應用程序使用哈希URL,那麼通過這些鏈接可用的內容不可用於這些最終用戶。如果您僅通過哈希URL創建內容部分而沒有回退,則這確實是一個問題。然而,如果您使用散列標籤鏈接來修改應用程序狀態,但如果頁面降級時不會保留含義,這絕對不是問題。

作爲示例,請考慮一個場景,其中有一個頁面,其中包含三個選項卡中的三個文本部分。現在有兩種可能的情況:第一種情況是,您將在加載頁面期間加載所有內容 - 並且標籤式小部件僅用於隱藏其他部分並顯示特定部分。因此,如果您在用於構建標籤大拇指的鏈接中使用散列URL,則僅使用它們來更改客戶端應用程序狀態。當javascript關閉/不可用時,只需用於構建選項卡式佈局的JavaScript不會運行,並且所有內容都立即可用 - 這是一種合理的優雅回退。在這種情況下,不同的應用程序狀態根本就不存在,所以散列URL會降低到僅指向html中的錨點 - 預期的目的。 在這種情況下,如果您要使用html5 pushstate,而不是哈希URL,這將是一個壞主意。如果用戶可能會將鏈接添加到特定標籤的原因。因爲你的服務器將不得不採取該網址,並向用戶展示他期望的客戶端狀態。這對於客戶端應該照顧自己的狀態管理的瘦服務器體系結構來說並不合適。您可以忽略服務器端的這一方面,並​​讓客戶端在頁面加載時從頭開始檢查URL,然後切換到適當的應用程序狀態。但是這仍然不是一個好主意,因爲你的服務器端路由系統關心的是額外url碎片的開銷,它應該忽略它,因爲從審美的角度來看,它應該不會被這個碎片困擾。這完全符合哈希網址的設計要求,強烈建議使用它們。如果相反在三個部分中,當單擊特定的選項卡縮略圖時會動態加載文本,那麼使用散列URL不是一個好主意。如果javascript不可用,原因是用戶將無法訪問鏈接的內容。這對搜索引擎優化尤其不利。在這種情況下,如果您在服務器端處理URL(通常情況下會被「劫持」和「混淆」)以使內容一般可用,則從最終用戶體驗以及SEO的角度來看都是非常好的。

第二種情況是客戶端擁有不支持html5 pushstate的過時瀏覽器。雖然上述觀點仍然存在,但是我還會爭辯說,強制用戶沒有與沒有JavaScript的降級相同級別的推送狀態是不合理的。許多最終用戶根本不知道他們爲什麼收到降級版本。

我建議您不要隨時使用最新技術的教條式動機標記,併爲您的使用場景決定最佳選擇。

+1

很好的答案,但我不太同意SEO部分。您可以使用散列網址,並且仍然可以將您的網頁編入索引。請參閱https://developers.google.com/webmasters/ajax-crawling/ – user123444555621 2012-07-09 22:00:03

+0

@ Pumbaa80我同意 – 2012-07-14 14:37:11

2

我個人更喜歡pushState,因爲它可以製作更好看的網址,我認爲這對用戶體驗很重要。

如果您想使用pushState,但不希望舊版瀏覽器支持出現問題,則可以使用history.pushState並使用history.js polyfill作爲散列回退。

+1

您的用戶體驗由多數用戶甚至沒有注意到的#決定? – Pascal 2016-07-16 15:18:57

2

目前,所有現代瀏覽器都支持pushState。因此pushStatelocation.hash好,但它是一個HTML5功能。

因此,location.hash並沒有死亡,事實上它會持續很長很長的時間。

一個很好的使用方法是使用支持pushState的lib,但也可以優雅地降級到使用location.hash
- https://github.com/browserstate/history.js

而且location.hash仍然是有用的跳轉到命名錨。 pushState將在構建Web應用程序方面提供巨大幫助。我期待着使用它。

1

這是一個相當古老的問題(5年+在本答覆的時間),但對現有答覆的很多評論要求基於「當前」狀態的更新進行更新。

這裏的交易:

HTML5的pushState的支持所有的主流瀏覽器。如果您也支持較舊的瀏覽器,history.js提供了一個很好的polyfill,可以讓您使用pushState進行本地化,並且可以輕鬆回退到舊版瀏覽器的舊版URL。然而,pushState本身是支持的,但這並不意味着它確實是一條路。

有一個非常重要的觀點沒有在任何舊的答案中提出,那就是哈希URL和pushState URL不僅在它們出現的方式上有所不同,而且它們在工作方式上實際上是不同的,太。這兩者之間的根本區別可能會導致您選擇一個在另一個之上。

pushState更漂亮,更乾淨,可用於在您的網站/您的應用中完全僞造導航。例如,GitHub使用它來不可見地替換所有導航。當您點擊他們網站上的任何鏈接時,javascript會攔截該點擊並將其轉變爲AJAX請求,該請求會更新頁面的內容而不會加載新頁面,而位置欄中的URL會更改爲與內容匹配牽強。 這是pushState旨在用於

在GitHub的情況下,http://mysite/page1http://mysite/page2都是有效的URL。它們與「真實」內容是「真實」的鏈接,並且最初訪問任一頁面都要經歷傳統的MVC方法。 GitHub在現代瀏覽器中使用pushState進行導航,但並不要求它 - 即pushState被用作「功能添加」(在他們看來),以便在導航時帶來更好的用戶體驗。當您在瀏覽器地址欄中複製鏈接時,您正在複製通過javascript & pushState形成的鏈接,但鏈接仍然真實有效。但是,如果您從抓撓並創建單頁應用程序開始並且未使用MVC框架,那麼很可能您實際上只有一個頁面,尤其是如果您未使用動態後端(即內容爲所有通過JavaScript檢索,從未由服務器生成)。在這種情況下,如果您使用pushState over hash URL,則需要處理瀏覽器中的URL不是真實URL的情況。我會說明。

的用戶加載單頁的應用程序:http://mysite/mainpage

在這一點上,瀏覽器欄包含真正的鏈接到你的應用程序,將用戶帶到他們目前看到了同樣的觀點:主頁。現在他們點擊一個鏈接,將他們帶到一個顯示某個活動細節的「頁面」。此時,您想更新位置欄以指示狀態更改。你要麼使用哈希URL和您的地址欄看起來像http://mysite/mainpage#charts/1或使用pushState的,它欺騙成爲http://mysite/mainpage/charts/1

如果您使用pushState的,這是不是一個真正的鏈接。通過瀏覽器的前進/後退按鈕導航將工作的偉大,並且用戶將在主頁轉到詳細頁都在地址欄中,並在應用程序(假設你正確處理狀態的改變),但如果用戶的書籤此鏈接或者複製和粘貼鏈接以共享它,將需要額外的服務器端voodoo。

您將需要請求重定向到/炫魅/圖表/ 1 /炫魅然後用JS來解決實際的URL和執行預期的狀態變化的操作。服務器重定向是絕對必需的。如果沒有可編寫腳本的http服務器,您無法在AWS或本地磁盤上託管此頁面。

現在,如果你使用的哈希的網址,您的網址,用戶將看到和互動與本來http://mysite/mainpage#/charts/1,這是一個有效的,真正的網址。瀏覽器明白,只有一個頁面,以及用戶是否複製和粘貼的鏈接或書籤它,你只需要處理JavaScript中的散列狀態,並且不需要任何服務器端魔法使事情的工作。

似乎沒有人提到pushState和哈希鏈接不是相互排斥的。 pushState的只是操縱瀏覽器的位置,是對用戶可見和現代瀏覽器中實現可靠的前進/後退導航的API。它沒有提到你的URL方案應該是什麼樣子。

在2017年,谷歌和幾乎所有其他的JS-能夠BOT瞭解哈希URL和遍歷他們就好了。 Google希望你使用#!可憎的最大化目的,但即使你不這樣做,你的網站可以通航就好了。

正確的答案是使用任何適合自己的需求。如果你有真正的URL並想僞造它們之間的導航,請使用pushState並繼續(對於較老的瀏覽器,可選擇使用polyfill)。但是,如果你有一個單頁的應用程序,不要假裝不要(除非你有一個很好的理由)。使用哈希網址來使您的生活更輕鬆,不會引入不必要的問題然後用pushState的操作這些哈希網址才能更好地利用前進/後退的支持

+0

我不確定你最後一句話的意思:你是否建議用location.hash替換URL,然後用pushState再次執行?這將如何幫助?從我所瞭解的pushState的主要問題是書籤,但如果我們這樣做,我們不會結束帶書籤的URL,無論如何需要重定向魔術?順便說一句,非常清楚和信息豐富,試圖讓所有這些信息感覺就像編寫一個難題,在這裏你真的觸及幾乎所有與討論有關的,謝謝 – 2017-09-08 13:17:46

+0

@FabioLolli關於最後一句話 - 在我的應用程序中,我有時會發現自己通過'pushState'和'replaceState'操作位置哈希。例如,最近的一個應用程序在按鍵上執行搜索。此搜索應更新用於書籤/轉發等的URL,但您不希望每個按鍵都用新條目填滿歷史堆棧(就像操作'location.hash'一樣)。相反,我在輸入時使用'replaceState',然後在一些防反跳超時之後,或者如果有必要,按回車鍵執行'pushState'。 – ijmacd 2017-10-23 03:52:23

+0

其實,截至2015年10月,Google不希望您使用#!. https://webmasters.googleblog.com/2015/10/deprecating-our-ajax-crawling-scheme.html – javajosh 2017-10-31 18:59:08