記、基於react-router的單頁應用

如今用react寫單頁應用基本上都是用react-router作前端路由了吧!最近在使用react-router的過程當中遇到了很多問題,在這裏總結一下。前端

瀏覽器urlreact

 react-router默認提供的history是 createHashHistory ,即它用到的是 URL 中的 hash(#)部分去建立形如 example.com/#/some/path 的路由,因此你會看到url多了相似 _key=s1gvrm  的 query,這真的很難看。並且這也不是官方在實際生產應用中所推薦的。要改變這種狀況的話,咱們須要去使用 createBrowserHistory在咱們的代碼中引入history,並在Router組件處調用 createBrowserHistory  方法便可。webpack

複製代碼
import React from "react"; import ReactDOM from "react-dom"; import createBrowserHistory from "history/lib/createBrowserHistory" import { Router,Route,Link,browserHistory,IndexRoute,IndexLink } from "react-router"; class App extends React.Component{ render(){ return( ... ); } }; ReactDOM.render(( <Router history={ createBrowserHistory() }> ... </Router> ),document.getElementById("app"));
複製代碼

其實關於url還有許多的細節,由於react-router自己就是構建於history之上的。單頁應用的url只不過是針對於react- router的一個標示而已,界面間的跳轉全然由react-router決定,react-router檢查當前url隨後渲染匹配的路由組件,由於是前端路由,因此若是直接在瀏覽器上輸入相對應的組件url,然後端卻不對此url作任何的匹配的話,可能會獲得404響應。web

組件通訊後端

這是一個用react寫代碼永遠都繞不開的話題。react-router是基於react開發的,因此它的每個route都是一個組件。路由組件間的通訊通常藉由Link來實現,而根據路由參數的不一樣,還能夠分紅兩種。這個很容易理解,由於這兩種方式和咱們平時寫的後臺路由並無什麼太大差異。瀏覽器

1 param,param經過/:param的方式傳遞。session

好比說咱們如今有一個顯示消息列表的路由組件,咱們須要在點擊每個消息的時候能跳轉到顯示被點擊消息詳情的路由組件。這個時候咱們消息詳情路由組件能夠是這樣定義的:react-router

<Route path="News_detail/:news_id" component={ news_detail }/>

在消息列表路由組件那裏咱們讓每一條消息都是這樣的一個Link:架構

<Link to={ `News_detail/${ element.timestamp }` } >{ element.news }</Link>
 這樣的話咱們的消息詳情組件就能經過   this.props.params 獲取到消息列表組件傳遞而來的   element.timestamp 參數了。

2 queryapp

<Link to="/Activity_Publish" query={{ timestamp : element.timestamp }}>編輯</Link>
 在    /Activity_Publish  映射的路由組件裏面能夠經過
var { query } = this.props.location; var timestamp = query.timestamp;

獲取到query參數。

相對於param,侷限性更小,你能夠根據須要傳遞更多的參數,只不過有點相似於get請求,傳遞的參數會附帶在url後面,看起來有點醜,並且幾乎無隱蔽性可言。

3 state

這種方式藉助了location 對象,location 對象能夠簡單的認爲是 url 的對象形式表示,這裏要提的是 location.state,每一個 URL 都會對應一個 state 對象,你能夠在對象裏存儲數據,但這個數據卻不會出如今 url 中。實際上,數據被存在了 sessionStorage 中,舊的路由組件能夠藉助這種方式傳遞數據給新的路由組件,可是會有個問題就是,新的路由組件雖然在首次被渲染的時候能夠成功拿到數據,可是若是此時瀏覽器被刷新的話,傳遞過來的數據也會消失。

<Link to="/Activity_Publish" state={{ timestamp : element.timestamp }}>編輯</Link>

按需加載

react-router協同webpack的使用能夠實現組件的按需加載,並且 這種按需加載徹底是異步的,這點特別酷炫,你再也不須要一口氣加載那麼大的js文件,即便裏面包含着許多用戶甚至都不會使用到的web組件。你能夠只根據需 要加載用戶瀏覽的那些組件,這個舉措將會幫你大大的下降首屏渲染的時間。

實現這個功能很簡單,好比在一開始你的路由是這樣子的:

複製代碼
...
import News_detail from "./marriage_component/activity/news_detail.jsx"; ... class App extends React.Component{ render(){ ... } }; ReactDOM.render(( <Router history={ createBrowserHistory() }> <Route path="/marriage_app" component={ App }> ... <Route path="/marriage_app/News_detail/:news_id" component={ News_detail }/> ...
複製代碼

把它改爲這樣就好了:

複製代碼
...
//import News_detail from "./marriage_component/activity/news_detail.jsx"; ... class App extends React.Component{ render(){ ... } }; ReactDOM.render(( <Router history={ createBrowserHistory() }> <Route path="/marriage_app" component={ App }> ... <Route path="/marriage_app/News_detail/:news_id" getComponent={ (nextState, callback) =>{ require.ensure( [ ], (require) => { callback(null, require("./marriage_component/activity/news_detail").default) }) } }/> ...
複製代碼

一開始的組件再也不須要被導入,webpack會幫你在須要的時候引入它。

最後

這種先後端分離的模式真的很贊,但彷佛對SEO並非很友好。若是真的須要SEO,又追求於實現先後端的真正解耦,是否是以Nodejs爲中間層的架構模式會成爲一種解決方案呢?

相關文章
相關標籤/搜索