history apiから見る主流フレームワークのルーティングメカニズム
6325 ワード
フロントエンドルーティングライブラリの役割は、アドレスバーを変更し、ブラウザの前進、後退をサポートし、ルーティングに対応するビューを同期することです.ここでreact-routerとその依存historyライブラリでルーティングメカニズムについて説明します.
テキストアドレス
前提条件
まず,フロントエンドルーティングメカニズムに依存するpushState,popstateイベント,hashおよび対応するhashChangeイベントについて簡単に紹介する. pushState,popstate html html 5のpushState、replaceStateメソッドの追加をサポートするブラウザでは、pushStateを設定することでブラウザhistoryスタックにレコード を追加できます.pushState()を設定、replaceState()の場合popstateイベントはトリガーされず、popstateイベントはブラウザの前進、後退ボタンまたはhistoryを呼び出すのみである.back()、history.forward()等時トリガ pushState()メソッドの最初のパラメータは、stateオブジェクトを指定し、history.stateまたはpopstateイベントコールバックeventオブジェクト取得 location.hash hashChange
pushStateメソッドがサポートされていないブラウザではlocationを変更できます.hashとhashChangeイベントによるルーティング機能比較 historyを設定するpushState(state,title,path)では、対応するルーティングにstateを設定できます.これにより、ルーティング間のデータ転送に新しいルートが提供されます.また、stateオブジェクトはローカルに保存され、リフレッシュページは依然として存在しますが、hash方式で実現されたルーティングは使用できません.react-router v 4バージョンではstateのシミュレーションも削除されます.
historyライブラリの紹介
historyライブラリは、ブラウザにwindowを内蔵する3つの異なる方法でhistoryオブジェクトを作成します.historyメソッドの拡張、
react-routerのルーティング実装(BrowserRouterとcreateBrowserHistory)
react-routerルーティング実装の概要historyを呼び出す.Pushジャンプルーティングの場合、内部でwindowを実行する.history.pushStateはブラウザhistoryスタックにレコードを追加しurlを変更し、 createBrowserHistoryにpopstateイベントを登録し、ユーザーがブラウザをクリックして前進、後退するとpopstateイベントで現在のeventを取得する.state,locationを再アセンブリし, を実行するhistoryライブラリはcreateBrowserHistoryメソッドを外部に暴露し、react-routerでcreateBrowserHistoryメソッドオブジェクトをインスタンス化し、 がルーティングが変更された場合
別々に見る
history.push
reactではhistoryを呼び出すことができます.Push(path,state)はルーティングをジャンプし、実際に実行されるのはcreateBrowserHistoryのpushメソッドです.
この方法では主に3つのことをします転送pathに基づいてstateパラメータはwindowとは異なるlocationを作成する.location,ここでlocationはこれらの属性 のみ
このlocationは、globalHistoryを実行する.pushState({ key, state }, null, href); 実行Routerに登録されているlistener
historyにおけるpopstateイベントの登録
popstateイベントがトリガーするとeventが得られる.state,createBrowserHistoryではこのstateと現在のwindowに基づいています.locationはlocationオブジェクトを再生成し、Routerコンポーネント登録のlistenerを実行し、UIを同期する
BrowserRouterコンポーネントにはcreateBrowserHistoryオブジェクトがインスタンス化され、Routerコンポーネントに渡されます.
Routerコンポーネントにhistoryを登録するListen()のリスニング関数で、サブコンポーネント(Route)で使用されるデータを保存します.
呼び出し時pushまたはpopstateイベントをトリガーすると、ここに登録されているlistenerはcreateBrowserHistoryによって実行され、setStateがトリガーされ、Routerのサブコンポーネントで一致するものが再レンダリングされます.
Routeにmatch状態があり、親コンポーネントpropsが変化したときに再計算されます.
まとめ
まとめるとreact-routerのルーティングメカニズムはhistoryライブラリを用いて、historyではpush,go,goBackなどの方法を実現し、popstateイベントを登録し、ルーティングジャンプ時にブラウザ内蔵のhistory apiを使用してhistoryスタック を操作するhistoryライブラリが外部に露出したhistoryオブジェクトはlistenメソッドを提供し、 を登録します.hsitoryを呼び出す.Pushまたはpopstateイベントがトリガーされた場合、listener を実行します. がレンダリングされる
本稿ではreact-routerでルーティングメカニズムを紹介するが,主流のルーティングライブラリの実現原理はそれほど悪くない, createBrowserHistory.js locationUtil.js BrowserRouter.js Router.js Route.js
テキストアドレス
前提条件
まず,フロントエンドルーティングメカニズムに依存するpushState,popstateイベント,hashおよび対応するhashChangeイベントについて簡単に紹介する.
history.pushState(state,title,path)
console.log(history.state)
window.addEventListener('popstate',(e)=>{
console.log(e.state)
})
pushStateメソッドがサポートされていないブラウザではlocationを変更できます.hashとhashChangeイベントによるルーティング機能
window.addEventListener('hashchange',e=>{
})
location.hash="test"
historyライブラリの紹介
historyライブラリは、ブラウザにwindowを内蔵する3つの異なる方法でhistoryオブジェクトを作成します.historyメソッドの拡張、
push,go,goBack,goForward , location、listen
は、ブラウザ環境以外のpolyfillを実現します.createBrowserHistory()
createHashHistory()
createMemoryHistory()
react-routerのルーティング実装(BrowserRouterとcreateBrowserHistory)
react-routerルーティング実装の概要
コンポーネント登録のコールバック関数を実行し、
コンポーネント登録のコールバック関数
コンポーネントにhistoryを登録する.Listen()コールバック関数、
コンポーネントでlocation、同期UI別々に見る
history.push
reactではhistoryを呼び出すことができます.Push(path,state)はルーティングをジャンプし、実際に実行されるのはcreateBrowserHistoryのpushメソッドです.
この方法では主に3つのことをします
location= {
path:
search:
hash:
state:
key
};
const location = createLocation(path, state, createKey(), history.location);
このlocationは、
および
コンポーネントで使用され、locationの値と
のpathマッチングに基づいて、正常なRouteコンポーネントレンダリングで指定されたcomponentに一致します.const action = "PUSH"
setState({ action, location });
const setState = nextState => {
Object.assign(history, nextState);
history.length = globalHistory.length;
transitionManager.notifyListeners(history.location, history.action);
};
historyにおけるpopstateイベントの登録
popstateイベントがトリガーするとeventが得られる.state,createBrowserHistoryではこのstateと現在のwindowに基づいています.locationはlocationオブジェクトを再生成し、Routerコンポーネント登録のlistenerを実行し、UIを同期する
const setState = nextState => {
Object.assign(history, nextState);
history.length = globalHistory.length;
transitionManager.notifyListeners(history.location, history.action);
};
const handlePop = location => {
const action = "POP";
setState({action,location)
}
コンポーネントBrowserRouterコンポーネントにはcreateBrowserHistoryオブジェクトがインスタンス化され、Routerコンポーネントに渡されます.
class BrowserRouter extends React.Component{
history = createHistory(this.props);
render() {
return ;
}
}
Routerコンポーネントにhistoryを登録するListen()のリスニング関数で、サブコンポーネント(Route)で使用されるデータを保存します.
getChildContext() {
return {
router: {
...this.context.router,
history: this.props.history,
route: {
location: this.props.history.location, //history location
match: this.state.match
}
}
};
}
componentWillMount{
this.unlisten = history.listen(() => {
this.setState({
match: this.computeMatch(history.location.pathname)
});
});
}
呼び出し時pushまたはpopstateイベントをトリガーすると、ここに登録されているlistenerはcreateBrowserHistoryによって実行され、setStateがトリガーされ、Routerのサブコンポーネントで一致するものが再レンダリングされます.
Routeにmatch状態があり、親コンポーネントpropsが変化したときに再計算されます.
state = {
match: this.computeMatch(this.props, this.context.router)
};
componentWillReceiveProps(nextProps, nextContext) {
this.setState({
match: this.computeMatch(nextProps, nextContext.router)
});
}
//computeMatch path ,
render() {
if (component) return match ? React.createElement(component, props) : null;
if (render) return match ? render(props) : null;
}
まとめ
まとめるとreact-routerのルーティングメカニズムは
コンポーネントはlistener
登録された傍受関数内部でsetState更新状態
のサブアセンブリ
のcomponentWillReceivePropsライフサイクル関数ではRouterのcontextが得られ、現在のpathとブラウザの現在のlocationから現在のrouteがmatchであるかどうかを判断し、一致するとcomponent本稿ではreact-routerでルーティングメカニズムを紹介するが,主流のルーティングライブラリの実現原理はそれほど悪くない,
pushState hash url
,
リファレンス