愛と勇気と缶ビール

ふしぎとぼくらはなにをしたらよいか

本当はそれなりに面倒くさいJavaScriptとhistoryとAjaxのお話

口上


historyAjaxJavaScripthistorypushhistory.pushStatehistory.replaceState

pushStatelocation.hash使Ajax10pushStateAjaxpushState

(pushState)




環境の分類


history3


(一)history.pushState

(二)history.pushStatewindow.onhashchange

(三)history.pushStatewindow.onhashchange


調2.233.hashsetInterval


pushStateを使う場合とhashを使う場合の遷移フロー


pushState/hash使Ajaxaonclick


リンク起因の遷移フロー (with pushState)

ユーザがリンク等をclick

これをJS側でキャッチして、必要があればpreventDefault。

該当するURLにxhr

リクエストが成功した場合、pushStateをhistoryをpush

(この時点でhistoryの状態が変化)

xhrのレスポンス(HTMLなりJSONなり)で、特定のDOM要素を書き換える

リンク起因の遷移フロー (with hash)

click

JSpreventDefault

location.href = ;

(history)

onhashchange, hashpollinghash

URLxhr

xhr(HTMLJSON)DOM


pushStatexhrsuccess/errorhistorypushhistoryhashxhrURL

(back, forward)


ブラウザバック起因の遷移フロー (with pushState)

popstate event

event handlerURL(statelocation.href)xhr

xhrDOM


popstate eventpushStatehistorypush


ブラウザバック起因の遷移フロー (with hash)

location.hashが変化

onhashchange, またはhashのpollingでhashの変化を検知

該当するURLにxhr

xhrのレスポンスで、DOM書き換え


まとめると、pushStateとhashに両対応する場合

  1. ページ内のリンク起因の遷移 with pushState
  2. ブラウザバック起因の遷移 with pushState
  3. ページ内のリンク起因の遷移 with hash
  4. ブラウザバック起因の遷移 with hash

の、4つの場合についてフローを整理して、historyがおかしなことにならないようにケアしてやる必要がある。逆に言えば、この4つについて整理できればコアの部分を書くのはそれほど難しくない。

現実のサイトに適用する場合の考慮すべき点

以上のようなことを踏まえた上で、固定されたヘッダー、フッター、ナビゲーションなどが存在し、それ以外の部分をAjaxでモリモリ書き換えて擬似画面遷移を行うようなサイトへの適用について考える。

通常リンクの書き換え

AjaxaddEventListener

2


(一)hrefonclick="next('http://example.com/foo')"anextpushState/hash

(二)class, attributenextbindnextbindAjaxevent delegate


2.HTMLonclick=""bindevent delegate使event delegate

1.onclickHTMLJShrefonclickAjax





URLの正規化



pushStatehashURL2http://example.com/foo/bar 


(一)http://example.com/foo/bar

(二)http://example.com/#page=foo/bar (#foo/bar)


pushStateURLURLDOM"http://example.com/foo/bar"xhr使HTTPrequest headerquery parameter

pushStateURLnext()URLhttp://example.com/foo/barhashURL使URL

next
function next(url) {
  if ( hasPushState ) {
    // pushStateがある場合の処理
    nextWithPushState(url);
  }
  else {
    // hashを使う場合の処理、ただしasHashUrlで通常のURLから2.のようなURLに変換
    nextWithHash(asHashUrl(url));
  }
}

pushStatehashURL


redirect

hashpollingpushStatehashpopstate eventpushStateURLpushState + Ajaxhash使hashURL

pushState使A(http://example.com/#page=foo/bar)pushState使B

pushState使http://example.com/#page=foo/barhashfallbackhistoryURL


(一)pushStatehttp://example.com/#page=foo/bar  -> http://example.com/foo/bar 

(二)pushStatehttp://example.com/foo/bar  -> http://example.com/#page=foo/bar 




pushStateJSpushStateUA


まとめと、hist.jsつくったよーという話


pushState/hashAjax




https://github.com/zentooo/hist.js


使readme


hist.configure({
  success: function(data) {
    // xhrが成功した場合のcallback
    document.getElementById("container").innerHTML = data;
  },
  error: function(xhr) {
    // xhrが失敗した場合のcallback
  }
});


  <a onclick="hist.next('http://example.com/foo/bar')">foobar</a>

addEventListenerhist.next()





(一)JSONrequest header X-Hist-XMLHttpRequest: 1

(二)hashURLhttp://example.com/#page=foo/bar

(三)




TwitterFacebookcrunchbang(#!)hash URLoptionwithBang: true


http://example.com/#!foo/bar

http://example.com/#!page=foo/bar


URL


 & 




Google API Expertが解説するHTML5ガイドブック

Google API Expertが解説するHTML5ガイドブック

  • 作者: 羽田野太巳,白石俊平,古籏一浩,太田昌吾
  • 出版社/メーカー: インプレスジャパン
  • 発売日: 2010/09/16
  • メディア: 単行本(ソフトカバー)
  • 購入: 15人 クリック: 461回
  • この商品を含むブログ (14件) を見る