摘要:談?wù)勛罱褂玫膩黹_發(fā)項(xiàng)目,感覺確實(shí)是爽的飛起,然而總感覺還是少了點(diǎn)什么。注意當(dāng)前版本依賴的是請不要安裝最新版。同樣的也有這個(gè)方法表示在離開路由前執(zhí)行。會深度優(yōu)先遍歷整個(gè)理由配置來尋找一個(gè)與給定的相匹配的路由。配置是建立在之上的。
談?wù)?/b>
最近使用的 React + webpack 來開發(fā)項(xiàng)目,感覺確實(shí)是爽的飛起,然而總感覺還是少了點(diǎn)什么。
對,是多頁面,每次請求頁面還要后端路由給你?多不爽啊,試試 react-router ,簡直掌控一切的感覺,只開放一個(gè)頁面路由接口,其他全給數(shù)據(jù)接口就了,可以和后端哥哥說拜拜了。
??????????? 啪啪啪啪啪~
先貼上官方文檔 https://github.com/rackt/react-router/tree/master/docs.
對了這里還有一份中文文檔(不過不是很全)http://react-guide.github.io/react-router-cn/.
react-router 是 React 的完整前端路由解決方案,特別在做一個(gè) spa 應(yīng)用的時(shí)候,他能實(shí)現(xiàn) url 和 視圖ui 的同步,并且支持后端渲染,異步按需加載等等。
由于 react-router 文檔的多變,這里的例子以當(dāng)前版本 1.0.1 為準(zhǔn)。(1.0之前文檔每一個(gè)版本的變動都很大,索多了都是淚)
所有支持 React 的瀏覽器。
倡議!建議大家也勸說身邊的人用現(xiàn)代化瀏覽器,關(guān)愛前端開發(fā)者。
npm install react-router@latest
同時(shí),react-router 是基于 history 開發(fā)的,這里你需要安裝 history。
注意 react-router 當(dāng)前版本 1.0.1 依賴的是 history 1.13.1 請不要安裝最新版。
不要問我為什么知道,被坑慘了;有同學(xué)問,那沒有辦法用 history 的最新版本嘛?畢竟這只是暫緩之計(jì),解決方案還是有的,那就是等 react-router 作者解決咯 ?。
npm install [email protected]
構(gòu)建工具的話,我依然建議是 webpack , React 和 webpack 是一對好兄弟。
npm install webpack
webpack的使用方法可以看我的前兩篇文章:
webpack-best-practice-最佳實(shí)踐-部署生產(chǎn)
如何使用webpack—webpack-howto
(求贊!??!)
// 加載依賴包,這是 es6 的語法(我好啰嗦)。 import React from "react" import { render } from "react-dom" // 這里從 react-router 引入了三個(gè)組件,先不解釋。 import { Router, Route, Link } from "react-router" const App = React.createClass({ render() { return () } }); const Inbox = React.createClass({ render() { return (App
{this.props.children}
- About
- Inbox
Inbox) } }); const About = React.createClass({ render() { return (About) } }); render((), document.getElementById("root"));
我就偷個(gè)懶把官方文檔的demo直接copy了。
直接先來看 render 下面的內(nèi)容,這里是用 jsx 語法。 最外層組件是 Router(可以把他看作是react-router提供的最外層容器) , 下一層是 Route,這個(gè)是路由組件。對應(yīng)關(guān)系如下:
/ --->
/about --->
/inbox --->
path 對應(yīng)路徑,component 對應(yīng)當(dāng)前路徑渲染的組件。
Route 里面的 Route 表示在父組件路由的 path 路徑下面的一級 path 對應(yīng)的路由,這里的路由是父子嵌套,對應(yīng)的組件也同樣是父子嵌套的。
如果是多級嵌套也同樣如此。
以上例子可以改寫成:
... const routerConfig = [ { path: "/", component: App, childrenRoutes: [ { path: "about", component: About }, { path: "inbox", component: Inbox }, ] } ]; render((), document.getElementById("root"));
這里的結(jié)構(gòu)就更清晰了,我是比較喜歡這種方式。
默認(rèn)的路由比如上面的例子,/ 對于的組件是 App , 如果 App 只是渲染了一個(gè)導(dǎo)航條,卻沒有自組件,那打開 比如 qiutc.me/ 的時(shí)候不是就沒有內(nèi)容了嗎。
把上面例子改一下
... // 添加組件 Index const Index = React.createClass({ render() { return (Index Index Index) } }); // 修改配置 const routerConfig = [ { path: "/", component: App, indexRoute: { component: Index }, childrenRoutes: [ { path: "about", component: About }, { path: "inbox", component: Inbox }, ] } ];
這里加了一個(gè) indexRoute ,表示他在沒有匹配子路由的時(shí)候,在 / 路由下渲染默認(rèn)的子組件 Index。
路由組件嵌套也是一樣的,比如:
{ path: "about", component: About, indexRoute: {component: AboutIndex} },
以此類推。
404 NotFound如果我們打開了一個(gè)沒有設(shè)置路由的鏈接,就必然需要一個(gè)友好的 404 頁面。配置如下:
... // 添加 404 組件 const NotFound = React.createClass({ render() { return (404 NotFound) } }); // 修改配置 const routerConfig = [ { path: "/", component: App, indexRoute: { component: Index }, childrenRoutes: [ { path: "about", component: About }, { path: "inbox", component: Inbox }, ] }, { path: "*", component: NotFound, } ];
如此簡單。
絕對路徑與重定向const routerConfig = [ { path: "/", component: App, indexRoute: { component: Index }, childrenRoutes: [ { path: "about", component: About }, { path: "inbox", component: Inbox, childrenRoutes: [ { path: "message/:id", component: Message, } ], }, ] }, { path: "*", component: NotFound, } ];
在這里我們訪問 /inbox/message/1 對于渲染 Message 組件,這個(gè)鏈接太長了,我們想直接 /message/1 那怎么辦,改路由結(jié)構(gòu)?太麻煩了!絕對路徑可以幫你做到這個(gè)。
把 path: "message/:id", 改為 path: "/message/:id", 就好了。
等等如果用戶之前收藏的鏈接是 /inbox/message/1 ,那不是就打不開了嘛,和后端路由一樣,react-router 也有重定向:redirect
const routerConfig = [ { path: "/", component: App, indexRoute: { component: Index }, childrenRoutes: [ { path: "about", component: About }, { path: "inbox", component: Inbox, childrenRoutes: [ { path: "/message/:id", component: Message, }, { path: "message/:id", onEnter: function (nextState, replaceState) { replaceState(null, "/messages/" + nextState.params.id); } } ], }, ] }, { path: "*", component: NotFound, } ];onEnter 方法表示進(jìn)入這個(gè)路由前執(zhí)行的方法,在進(jìn)入 /inbox/messages/:id 的前,執(zhí)行
function (nextState, replaceState) { replaceState(null, "/messages/" + nextState.params.id); }
nextState表示要進(jìn)入的下一個(gè)路由,這里就是 /inbox/messages/:id ,replaceState 表示替換路由狀態(tài)的方法,把 /inbox/messages/:id 替換成 /messages/:id,然后就可以重定向到 /messages/:id。
同樣的也有 onLeave 這個(gè)方法表示在離開路由前執(zhí)行。
———————————————————
當(dāng)然如果你用的是 jsx 語法,有更簡單的組件可以實(shí)現(xiàn):
import { Redirect } from "react-router" React.render((路徑匹配原理 嵌套關(guān)系), document.getElementById("root")) {/* 跳轉(zhuǎn) /inbox/messages/:id 到 /messages/:id */}
React Router 使用路由嵌套的概念來讓你定義 view 的嵌套集合,當(dāng)一個(gè)給定的 URL 被調(diào)用時(shí),整個(gè)集合中(命中的部分)都會被渲染。嵌套路由被描述成一種樹形結(jié)構(gòu)。React Router 會深度優(yōu)先遍歷整個(gè)理由配置來尋找一個(gè)與給定的 URL 相匹配的路由。
簡單來講,就是說,匹配的時(shí)候會先匹配到外層路徑,然后依次遍歷到內(nèi)層。
比如 /inbox/messages/:id 會先匹配 /,渲染 / 對應(yīng)的組件 App,然后再到 / 的下一層尋找 /inbox ,同樣渲染 /inbox 對應(yīng)的組件 Inbox,依次類推,直到到 message/:id。
tip:使用絕對路徑可以忽略嵌套關(guān)系,如上面例子。
路徑語法路由路徑是匹配一個(gè)(或一部分)URL 的 一個(gè)字符串模式。大部分的路由路徑都可以直接按照字面量理解,除了以下幾個(gè)特殊的符號:
/:paramName – 匹配一段位于 /、? 或 # 之后的 URL。 命中的部分將被作為一個(gè)參數(shù)
(/) – 在它內(nèi)部的內(nèi)容被認(rèn)為是可選的
/* – 匹配任意字符(非貪婪的)直到命中下一個(gè)字符或者整個(gè) URL 的末尾,并創(chuàng)建一個(gè) splat 參數(shù)
優(yōu)先級// 匹配 /hello/michael 和 /hello/ryan // 匹配 /hello, /hello/michael 和 /hello/ryan // 匹配 /files/hello.jpg 和 /files/path/to/hello.jpg
最后,路由算法會根據(jù)定義的順序自頂向下匹配路由。因此,當(dāng)你擁有兩個(gè)兄弟路由節(jié)點(diǎn)配置時(shí),你必須確認(rèn)前一個(gè)路由不會匹配后一個(gè)路由中的路徑。例如:
第二個(gè)是不會被執(zhí)行的。
拿到參數(shù)路徑的比如上面的 /messages/:id ,這個(gè)id可能是我們在 Message 獲取數(shù)據(jù)時(shí)需要的 id。
他會被當(dāng)做一個(gè)參數(shù)傳給 params,parmas 會傳給 Message 組件的 props:
const Message = React.createClass({ render: function() { return ({ this.props.params.id }); } });
這樣就可以獲取到了。
history 配置React Router 是建立在 history 之上的。 簡而言之,一個(gè) history 知道如何去監(jiān)聽瀏覽器地址欄的變化, 并解析這個(gè) URL 轉(zhuǎn)化為 location 對象, 然后 router 使用它匹配到路由,最后正確地渲染對應(yīng)的組件。
常用的 history 有三種形式, 但是你也可以使用 React Router 實(shí)現(xiàn)自定義的 history。
createHashHistory
createBrowserHistory
createMemoryHistory
這三個(gè)有什么區(qū)別呢: createHashHistory這是一個(gè)你會獲取到的默認(rèn) history ,如果你不指定某個(gè) history 。它用到的是 URL 中的 hash(#)部分去創(chuàng)建形如 example.com/#/some/path 的路由。
這個(gè) 支持 ie8+ 的瀏覽器,但是因?yàn)槭?hash 值,所以不推薦使用。
Browser history 是由 React Router 創(chuàng)建瀏覽器應(yīng)用推薦的 history。它使用 History API 在瀏覽器中被創(chuàng)建用于處理 URL,新建一個(gè)像這樣真實(shí)的 URL example.com/some/path。
Memoryhistory不會在地址欄被操作或讀取。
使用import { createBrowserHistory, useBasename } from "history"; const historyConfig = useBasename(createHistory)({ basename: "/" // 根目錄名 }); ... render((Link&IndexLink Link), document.getElementById("root"));
我們在最開頭看到這樣一個(gè)東西:
const App = React.createClass({ render() { return () } });App
{this.props.children}
- About
- Inbox
Link 會被渲染成 a ,to 其實(shí)就是 href ,
但是 react-router 會阻止默認(rèn)跳轉(zhuǎn)頁面,而改成 history 路由的變換。
參數(shù):
to
切換到的路由地址
query
跟在 url 的 query 參數(shù),比如
query={{q: "que"}} 對應(yīng) `/example?a=que
這里的 query 同樣可以像 params 會被傳入下一個(gè)路由組件的 props
hash
跟在 url 的 hash 參數(shù),比如
hash={111} 對應(yīng) `/example#111
這里的 query 同樣可以像 params 會被傳入下一個(gè)路由組件的 props
activeClassName
當(dāng)前 url 路徑如果和 Link 的 to 匹配 這個(gè) Link 就會有一個(gè)定義的屬性,比如:
在 /index 下 / 這里渲染出來的 a 標(biāo)簽會有一個(gè)激活的 active 類名,還會有一個(gè)顏色 red / 這里渲染出來的 a 標(biāo)簽就不會有以上屬性
activeStyle
同上
onClick
點(diǎn)擊的時(shí)候執(zhí)行的函數(shù),會傳入一個(gè) e 事件對象,你可以 e.stopPropagation() 阻止默認(rèn)路由切換。
在上面有一個(gè)問題如果:
在 / 下 和 /index / 這個(gè) Link 渲染出來的 a 標(biāo)簽都會激活 active 屬性,并且會帶上 color: "red" 因?yàn)?/ 和 /index 和 / 都是匹配的
這時(shí)候就可以用:
未完待續(xù)/ 只會在 / 下唄激活,在 /index 或者其他下面,不會被激活
關(guān)于 根據(jù)路由按需異步加載js 和 服務(wù)器端渲染路由視圖 以及 react-router的更高級用法 會在下一篇文章來探討。
畢竟哥也需要去深入研究一下才敢獻(xiàn)丑。
?
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/78278.html
摘要:當(dāng)年的加載在沒有前端工程化之前,基本上是我們是代碼一把梭,把所需要的庫和自己的代碼堆砌在一起,然后自上往下的引用就可以了。而且對于前后端的技術(shù)要求較高,所以對于項(xiàng)目未必是最有效的方案。 當(dāng)年的 js 加載 在沒有 前端工程化之前,基本上是我們是代碼一把梭,把所需要的庫和自己的代碼堆砌在一起,然后自上往下的引用就可以了。 那個(gè)時(shí)代我們沒有公用的cdn,也沒有什么特別好的方法來優(yōu)化加載j...
摘要:這對復(fù)雜問題定位是有好處的。同時(shí),也是純函數(shù),與的是純函數(shù)呼應(yīng)。強(qiáng)約束約定,增加了內(nèi)聚合性。通過約定和全局的理解,可以減少的一些缺點(diǎn)。約定大于配置也是框架的主要發(fā)展方向。 React+Redux非常精煉,良好運(yùn)用將發(fā)揮出極強(qiáng)勁的生產(chǎn)力。但最大的挑戰(zhàn)來自于函數(shù)式編程(FP)范式。在工程化過程中,架構(gòu)(頂層)設(shè)計(jì)將是一個(gè)巨大的挑戰(zhàn)。要不然做出來的東西可能是一團(tuán)亂麻。說到底,傳統(tǒng)框架與rea...
摘要:前言最近將公司項(xiàng)目的從版本升到了版本,跟完全不兼容,是一次徹底的重寫。升級過程中踩了不少的坑,也有一些值得分享的點(diǎn)。沒有就會匹配所有路由最后不得不說升級很困難,坑也很多。 前言 最近將公司項(xiàng)目的 react-router 從 v3 版本升到了 v4 版本,react-router v4 跟 v3 完全不兼容,是一次徹底的重寫。這也給升級造成了極大的困難,與其說升級不如說是對 route...
摘要:概述相對于幾乎是重寫了新版的更偏向于組件化。汲取了很多思想,路由即是組件,使路由更具聲明式,且方便組合。如果你習(xí)慣使用,那么一定會很快上手新版的。被一分為三。不止是否有意義參考資料遷移到關(guān)注點(diǎn)官方文檔 概述 react-router V4 相對于react-router V2 or V3 幾乎是重寫了, 新版的react-router更偏向于組件化(everything is comp...
摘要:解決了什么問題首先,它搭配組件,可以組織組件結(jié)構(gòu)代碼,授權(quán)路由的控制。有兩種方式核心的各自做了什么事首先它們都是基于構(gòu)建,也就是的組件的路由,至于各自做了什么。去看官方文檔,里面描述了每一個(gè)組件路由做了什么事。 React-Router解決了什么問題? 首先,它搭配React組件,可以組織React組件結(jié)構(gòu)代碼,授權(quán)路由的控制。應(yīng)該展示什么樣的組件,通過React-Router去匹配它...
閱讀 2850·2023-04-25 20:02
閱讀 1451·2021-11-11 16:55
閱讀 637·2021-09-26 09:46
閱讀 6229·2021-09-22 15:55
閱讀 1835·2021-08-09 13:41
閱讀 1589·2019-08-30 15:52
閱讀 2391·2019-08-30 14:13
閱讀 3314·2019-08-26 13:48