之前看react-router的時候寫的筆記,搬過來充數
Router
筆者解讀:React Router的組件,可保持UI和URL的同步 看名字的話,react-router大概跟其他語言里面路由的功能和作用是差不多的,差別應該是在用法和形式上面,也就是神一樣,形不一樣(容我裝一下AC之間)。
這好像是一個官方文檔上面的例子:
import React from 'react' import{ render } from 'react-dom'
// 首先我們需要導入一些組件...
import{ Router, Route, Link } from 'react-router' const App = React.createClass({ render(){ return( <div>
<h1>App</h1>
{/* 把 <a> 變成 <Link> */} <ul>
<li><Link to="/about">About</Link></li>
<li><Link to="/inbox">Inbox</Link></li>
</ul>
{/* 接着用 `this.props.children` 替換 `<Child>` router 會幫我們找到這個 children */} {this.props.children} </div>)
}}) // 最后,我們用一些 <Route> 來渲染 <Router>。 // 這些就是路由提供的我們想要的東西。
React.render( ( <Router>
<Route path="/" component={App}>
<Route path="about" component={About}/>
<Route path="inbox" component={Inbox}/></Route>
</Router>), document.body)
react-router會為我們搭建嵌套UI eg: 當路徑是/about時,react-router會搭建出
<App> <About /> </App>
這樣的東東。
在Inbox內部嵌套Message,是的還是一個貼過來的例子:
// 新建一個組件讓其在 Inbox 內部渲染
const Message = React.createClass({ render() { return <h3>Message</h3>
} }) const Inbox = React.createClass({ render() { return ( <div>
<h2>Inbox</h2>
{/* 渲染這個 child 路由組件 */} {this.props.children || "Welcome to your Inbox"} </div>
) } }) React.render(( <Router>
<Route path="/" component={App}>
<Route path="about" component={About} />
<Route path="inbox" component={Inbox}> {/* 添加一個路由,嵌套進我們想要嵌套的 UI 里 */} <Route path="messages/:id" component={Message} />
</Route>
</Route>
</Router>
), document.body)
Router與Route一樣都是react的組件 Route的path屬性表示路由組件對應的路徑,可以是絕對路徑也可以是相對路徑 在Route中可以用component指定單個組件,或者通過components指定多個組件集合 param通過/:param的方式傳遞(path="messages/:id"),這種寫法與express以及ruby on rails一致,符合RestFul規范。
獲取URL參數
const Message = React.createClass({ componentDidMount(){ // 來自於路徑 `/inbox/messages/:id`
const id =this.props.params.id fetchMessage(id,function(err, message){ this.setState({ message: message }) } )}, // ...
})
還可以用 query 字符串來訪問參數。 比如要訪問 /foo?bar=baz,
你可以通過訪問this.props.location.query.bar 從 Route 組件中獲得 "baz" 。
路由配置
其實就是告訴router怎樣匹配URL以及匹配完之后怎樣去執行代碼 例:添加一個默認的首頁 URL為/時,
想渲染一個App中的組件,但是這個時候App中render中的子組件也就是this.props.children還是undefined,
這個時候我們就需要用IndexRoute設置默認的頁面
<IndexRoute component={Dashboard} />
如果在路徑中使用絕對路徑就可以做到像這樣, /inbox/messages/:id 變成 /messages/:id 但是細心的盆宇會發現,
其實這樣做是改變了URL,做出如此不符合規范的行為,就會造成這樣的現象,
如果有人訪問/inbox/messages/5時就會找不到頁面,那么如何補救呢,
這時候Redirect就出現了 Redirect是一個重定向組件,有from和to兩個屬性 我們可以用Redirect重新定向這個URL。
<Route path="inbox" component={Inbox} >
<Route path="/messages/:id" component={Message} />
{/*跳轉 /inbox/messages/:id 到 /messages/:id */} <Redirect from="messages/:id" to="/messages/:id" />
</Route>
進入和離開的Hook Route可以定義onEnter和onLeave兩個hook,
hook會在頁面跳轉確認時觸發一次:權限驗證或在路由跳轉之前將一些數據持久化保存起來 在路由跳轉過程中,
onLeave hook 會在所有將離開的路由中觸發,從最下層的子路由開始直到最外層父路由結束。
然后onEnter hook會從最外層的父路由開始直到最下層子路由結束。
一個比較通俗易懂的例子, 點擊鏈接,從/messages/5跳轉到/about,hook的執行就是下面這個樣子:
/messages/:id 的 onLeave /inbox 的 onLeave
/about的 onEnter
除了上面這種組件一樣的方法之外, 路由的配置書寫方法還可以這樣子,
const routeConfig =[{ path:'/', component: App, indexRoute:{ component: Dashboard }, childRoutes:[ { path:'about', component: About }, { path:'inbox', component: Inbox, childRoutes:[{ path:'/messages/:id', component: Message }, { path:'messages/:id', onEnter:function(nextState, replaceState){ replaceState(null,'/messages/'+ nextState.params.id)} }] }] }] React.render(<Router routes={routeConfig}/>, document.body)
很像寫配置文件一樣的。
路由匹配原理
路由有三個屬性來決定它是否與一個“URL”相匹配
嵌套關系 路徑語法 優先級
嵌套關系
官方解釋是醬紫的:React-Router 使用路由嵌套的概念來讓你定義 view 的嵌套集合,當一個給定的 URL 被調用時,整個集合中(命中的部分)都會被渲染。嵌套路由被描述成一種樹形結構。React Router 會深度優先遍歷整個路由配置來尋找一個與給定的 URL 相匹配的路由。 就是說,react-router的路由是使用一種組件相互嵌套的方式定義的,這個跟react-redux里面組件的結構也很一致
路徑語法:
路由路徑是匹配一個(或一部分)URL的一個字符串模式。
:paramName 匹配一段位於/,?或# 之后的URL。
命中的部分將被作為一個參數 () 在它內部的內容被認為是可選的 * 匹配任意字符(非貪婪的)直到命中下一個自負或者整個URL的末尾,並創建一個splat參數
<Route path="/hello/:name">// 匹配 /hello/michael 和 /hello/ryan
<Route path="/hello(/:name)">// 匹配 /hello, /hello/michael 和 /hello/ryan
<Route path="/files/*.*">// 匹配 /files/hello.jpg 和 /files/path/to/hello.jpg
優先級
路由算法會根據定義的順序自頂向下匹配路由,
因此,當你擁有兩個兄弟路由節點配置時,你必須確認前一個路由不會匹配后一個路由中的路徑。
例如,千萬不要這么做:
<Route path="/comments".../>
<Redirect from="/comments".../>
這樣的話,前面配好的路由就會被重定向。
未完待續。。。