react-router 中的history

react-router 是建立在history之上的;我們來談談這個history吧。

github: mjackson/history

history 一個管理js應用session會話歷史的js庫。它將不同環境(瀏覽器,node...)的變數統一成了一個簡易的API來管理歷史堆棧、導航、確認跳轉、以及sessions間的持續狀態。

//基本 使用nimport { createHistory } from historynnconst history = createHistory()nn// 當前的地址nconst location = history.getCurrentLocation()nn// 監聽當前的地址變換nconst unlisten = history.listen(location => {n console.log(location.pathname)n})nn// 將新入口放入歷史堆棧nhistory.push({n pathname: /the/path,n search: ?a=query,nn // 一些不存在url參數上面的當前url的狀態值n state: { the: state }n})nn// When youre finished, stop the listenernunlisten()n

你也可以使用 history對象來的方法來改變當前的location:

  • push(location)
  • replace(location)
  • go(n)
  • goBack()
  • goForward()

一個 history 知道如何去監聽瀏覽器地址欄的變化, 並解析這個 URL 轉化為 location 對象, 然後 router 使用它匹配到路由,最後正確地渲染對應的組件。

location對象包括:

pathname 同window.location.pathnamensearch 同window.location.searchnstate 一個捆綁在這個地址上的object對象naction PUSH, REPLACE, 或者 POP中的一個nkey 唯一IDn

常用的三種history

// HTML5 history, 推薦nimport createHistory from history/lib/createBrowserHistorynn// Hash historynimport createHistory from history/lib/createHashHistorynn// 內存 history (如:node環境)nimport createHistory from history/lib/createMemoryHistoryn

createHashHistory

這是一個你會獲取到的默認 history ,如果你不指定某個 history (即 <Router>{/* your routes */}</Router>)。它用到的是 URL 中的 hash(#)部分去創建形如 http://example.com/#/some/path 的路由。

Hash history 是默認的,因為它可以在伺服器中不作任何配置就可以運行,並且它在全部常用的瀏覽器包括 IE8+ 都可以用。但是我們不推薦在實際生產中用到它,因為每一個 web 應用都應該有目的地去使用createBrowserHistory。

createBrowserHistory

Browser history 是由 React Router 創建瀏覽器應用推薦的 history。它使用 History API 在瀏覽器中被創建用於處理 URL,新建一個像這樣真實的`URL example.com/some/path`

伺服器配置

首先伺服器應該能夠處理 URL 請求。處理應用啟動最初的 / 這樣的請求應該沒問題,但當用戶來回跳轉並在 /accounts/123 刷新時,伺服器就會收到來自 /accounts/123 的請求,這時你需要處理這個 URL 並在響應中包含 JavaScript 程序代碼。

一個 express 的應用可能看起來像這樣的:

const express = require(express)nconst path = require(path)nconst port = process.env.PORT || 8080nconst app = express()nn// 通常用於載入靜態資源napp.use(express.static(__dirname + /public))nn// 在你應用 JavaScript 文件中包含了一個 script 標籤n// 的 index.html 中處理任何一個 routenapp.get(*, function (request, response){n response.sendFile(path.resolve(__dirname, public, index.html))n})nnapp.listen(port)nconsole.log("server started on port " + port)n

如果你的伺服器是 nginx,請使用 try_files directive:

server {n ...n location / {n try_files $uri /index.htmln }n}n

當在伺服器上找不到其他文件時,這就會讓 nginx 伺服器生成靜態文件和操作 index.html 文件。

createMemoryHistory

Memory history 不會在地址欄被操作或讀取。這就解釋了我們是如何實現伺服器渲染的。同時它也非常適合測試和其他的渲染環境(像 React Native )。

實現示例

import React from reactnimport createBrowserHistory from history/lib/createBrowserHistorynimport { Router, Route, IndexRoute } from react-routernimport App from ../components/Appnimport Home from ../components/Homenimport About from ../components/Aboutnimport Features from ../components/FeaturesnnReact.render(n <Router history={createBrowserHistory()}>n <Route path=/ component={App}>n <IndexRoute component={Home} />n <Route path=about component={About} />n <Route path=features component={Features} />n </Route>n </Router>,n document.getElementById(app)n)n

推薦閱讀:

你不知道的前端演算法之熱力圖的實現
精讀模態框的最佳實踐
什麼是臟檢測,angular的雙向綁定機製為什麼叫臟檢測,雙向綁定具體細節是怎麼樣的?

TAG:前端开发 | React | 前端工程师 |