一席揽、路由
1.1汗盘、 SPA的理解
1.單頁Web應(yīng)用(single page web application注祖,SPA)猾蒂。
2.整個(gè)應(yīng)用只有一個(gè)完整的頁面。
3.點(diǎn)擊頁面中的鏈接不會(huì)刷新頁面是晨,只會(huì)做頁面的局部更新肚菠。
4.數(shù)據(jù)都需要通過ajax請求獲取, 并在前端異步展現(xiàn)。
1.2罩缴、路由的理解
1.什么是路由?
1.一個(gè)路由就是一個(gè)映射關(guān)系(key:value)
2.key為路徑, value可能是function或component
2.路由分類
后端路由:
1蚊逢、理解: value是function, 用來處理客戶端提交的請求层扶。
2、注冊路由: router.get(path, function(req, res))
3时捌、工作過程:當(dāng)node接收到一個(gè)請求時(shí), 根據(jù)請求路徑找到匹配的路由, 調(diào)用路由中的函數(shù)來處理請求, 返回響應(yīng)數(shù)據(jù)
前端路由:
1怒医、瀏覽器端路由炉抒,value是component奢讨,用于展示頁面內(nèi)容。
2焰薄、注冊路由: <Route path="/test" component={Test}>
3拿诸、工作過程:當(dāng)瀏覽器的path變?yōu)?test時(shí), 當(dāng)前路由組件就會(huì)變?yōu)門est組件
一、React Router 5
react-router-dom的理解
1塞茅、react的一個(gè)插件庫亩码。
2、專門用來實(shí)現(xiàn)一個(gè)SPA應(yīng)用野瘦。
3描沟、基于react的項(xiàng)目基本都會(huì)用到此庫。
下載react-router-dom:
npm install --save react-router-dom
內(nèi)置組件
1鞭光、<BrowserRouter>:用于將應(yīng)用程序包裹在 HTML5 history API 的 <BrowserRouter> 中吏廉,使得 React Router 可以監(jiān)聽 URL 的變化,并且匹配當(dāng)前 URL 對應(yīng)的 Route 進(jìn)行渲染惰许。
2席覆、<HashRouter>:用于將應(yīng)用程序包裹在 hash history 的 <HashRouter> 中,適用于不支持 HTML5 history API 的環(huán)境汹买,如舊版瀏覽器或一些特殊環(huán)境佩伤。
3、<Route>:用于聲明路由規(guī)則晦毙,即指定路徑對應(yīng)的組件渲染內(nèi)容生巡。<Route> 根據(jù)當(dāng)前 URL 路徑匹配對應(yīng)的路徑規(guī)則,并渲染相關(guān)組件见妒。
4障斋、<Redirect>:用于在匹配到某個(gè)路徑時(shí)重定向到另一個(gè)路徑,可以用于處理一些特殊場景徐鹤,比如用戶訪問的舊路徑需要重定向到新路徑垃环。
5、<Link>:用于在應(yīng)用中創(chuàng)建導(dǎo)航鏈接返敬,點(diǎn)擊該鏈接后會(huì)更新 URL 而不會(huì)重新加載頁面遂庄,實(shí)現(xiàn)單頁應(yīng)用的導(dǎo)航功能。
6劲赠、<NavLink>:是 <Link> 的一個(gè)增強(qiáng)版本涛目,除了具有 <Link> 的功能外秸谢,還可以添加 activeClassName 和 activeStyle 等屬性,用于定義鏈接激活時(shí)的樣式霹肝。
7估蹄、<Switch>:用于包裹多個(gè) <Route> 組件,它會(huì)遍歷所有子 <Route> 組件沫换,并只渲染與當(dāng)前 URL 匹配的第一個(gè) <Route> 或 <Redirect> 組件臭蚁,避免多個(gè)路由同時(shí)匹配的問題
1.1、BrowserRouter 和 HashRouter 的區(qū)別
1.底層原理不一樣
??BrowserRouter使用的是H5的history API讯赏,不兼容IE9及以下版本垮兑。HashRouter使用的是URL的哈希值。
2.path表現(xiàn)形式不一樣
??BrowserRouter的路徑中沒有#,例如: localhost:3000/demo/test
??HashRouter的路徑包含#,例如: localhost:3000/#/demo/test
3.刷新后對路由state參數(shù)的影響
??(1).BrowserRouter沒有任何影響漱挎,因?yàn)閟tate保存在history對象中系枪。
??(2).HashRouter刷新后會(huì)導(dǎo)致路由state參數(shù)的丟失!!!
原生html中,靠<a>跳轉(zhuǎn) 不同的頁面
<a href="./about.html">About</a>
<a href="./home.html">Home</a>
在React中靠路由鏈接實(shí)現(xiàn)切換組件
首先我們把a(bǔ)bout.html和home.html改成兩個(gè)組件
然后引入 Link 和 Route 磕谅,通過<Route>注冊路由私爷,通過 <Link />進(jìn)行切換組件
import {HashRouter, Link , Route} from "react-router-dom";
hash路由模式
<HashRouter>
跳轉(zhuǎn)路由
<Link to="/about" />
<Link to="/home" />
注冊路由
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
</HashRouter>
1.2、<NavLink>是<Link>的一個(gè)特定版本膊夹,會(huì)在匹配上當(dāng)前的url的時(shí)候給已經(jīng)渲染的元素添加參數(shù)衬浑,組件的屬性有:
- activeClassName(string):設(shè)置選中樣式,默認(rèn)值為active
- activeStyle(object):當(dāng)元素被選中時(shí)割疾,為此元素添加樣式
- exact(bool):為true時(shí)嚎卫,只有當(dāng)導(dǎo)致和完全匹配class和style才會(huì)應(yīng)用
- strict(bool):為true時(shí),在確定為位置是否與當(dāng)前URL匹配時(shí)宏榕,將考慮位置pathname后的斜線
- isActive(func)判斷鏈接是否激活的額外邏輯的功能
所以開發(fā)中一般使用<NavLink>
路由的基本使用
import { HashRouter, Route, NavLink } from "react-router-dom";
<HashRouter>
跳轉(zhuǎn)路由
<NavLink to="/about" />
<NavLink to="/home" />
注冊路由
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
</HashRouter>
1.3拓诸、Switch和Redirect
當(dāng)我們注冊路由,注冊了同樣的路徑麻昼,渲染不同的路由組件奠支,當(dāng)跳轉(zhuǎn)路由的時(shí)候有兩個(gè)路由能匹配上就會(huì)出現(xiàn)兩個(gè)路由組件全部展示的情況,如下圖
<Route path="/home" component={Home}></Route>
<Route path="/home" component={Test}></Route>
正常來說一個(gè)路徑匹配一個(gè)路由抚芦,上圖明顯有問題倍谜,如果每個(gè)同樣的路徑匹配多個(gè)路由組件,如果我們要展示兩個(gè)路由組件為什么不把兩個(gè)路由組件合成一個(gè)組件呢叉抡,當(dāng)?shù)谝粋€(gè)路由組件匹配上以后尔崔,如果下面還有無數(shù)個(gè)相同路徑的路由組件,會(huì)匹配無數(shù)次路由會(huì)導(dǎo)致性能損耗褥民,所以一個(gè)路徑匹配一個(gè)路由季春。這個(gè)時(shí)候我們會(huì)使用Switch:Switch實(shí)現(xiàn)提高匹配效率的效果,匹配到第一個(gè)后面就不會(huì)匹配了
<Switch>
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
<Route path="/home" component={Test}></Route>
一般寫在所有路由注冊的最下方消返,當(dāng)所有路由都無法匹配時(shí)载弄,跳轉(zhuǎn)到Redirect指定的路由
<Redirect to="/about" />
</Switch>
路由的嚴(yán)格模式
如上圖耘拇,我們注冊的路由組件路徑和跳轉(zhuǎn)路由的開始的路徑能匹配上,就能正常展示路由組件的頁面宇攻,如下圖惫叛,跳轉(zhuǎn)的路徑是 /home/index,注冊路由的地址是 /home,因?yàn)樘D(zhuǎn)路徑前面的地址是 /home,默認(rèn)是模糊模式逞刷,所以成功匹配展示注冊路由組件
如果需要注冊的路由組件路徑和跳轉(zhuǎn)路由的開始的路徑完全一樣:
路由開啟嚴(yán)格匹配
嚴(yán)格模式不要隨便開啟嘉涌,這樣會(huì)影響二級(jí)路由
<Route exact path="/about" component={About}></Route>第一種方法,寫exact屬性就行
<Route exact={true} path="/home" component={Home}></Route>第二種方法亲桥,寫exact={true}
嵌套路由
這里是父組件洛心,正常寫路由就行
<Switch>
<Route path="/about" component={About}></Route>
<Route path="/home" component={Home}></Route>
<Redirect to="/about" />
</Switch>
這里是子路由的組件固耘,子路由注冊的時(shí)候需要加上父組件的路徑
<Switch>
<Route path="/home/news" component={News}/>//嵌套路由需要加上父路徑
<Redirect to="/home/news"/>
</Switch>
React Router 5路由傳參
跳轉(zhuǎn)路由
向路由組件傳遞params參數(shù)
<Link to={`/home/message/detail/${i.id}/${i.title}`} children={i.title} />
向路由組件傳遞search參數(shù)
<Link to={`/home/message/detail/?id=${i.id}&title=${i.title}`} children={i.title} />
向路由組件傳遞state參數(shù)
<Link to={{pathname: "/home/message/detail", state: {id:i.id,title:i.title}}} children={i.title} />
注冊路由
聲明接收params參數(shù)
<Route path="/home/message/detail/:id/:title" component={Detail} />
search參數(shù)無需聲明接收题篷,正常注冊路由即可
<Route path="/home/message/detail" component={Detail} />
state參數(shù)無需聲明接收,正常注冊路由即可
<Route path="/home/message/detail" component={Detail} />
路由組件接受路由參數(shù)
接收params參數(shù)
const {id, title} = this.props.match.params;
接收search參數(shù)
import qs from "querystring";
const {id, title} = qs.parse((this.props.location.search).slice(1));
接收state參數(shù)
const {id, title} = this.props.location.state || {};
接收search參數(shù)厅目,需要下載querystring npm i querystring
querystring基本使用
import qs from "querystring";
let obj = { name: 'tom', age: 18}; //name=tom&age=18 key=value&key=value
console.log(qs.stringify(obj));
let str = 'carName=奔馳&price=199';
console.log(qs.parse(str));
路由跳轉(zhuǎn)模式push和replace
push(/path) 里面的path會(huì)進(jìn)入路由棧番枚,
replace(/path) 不會(huì),但是它里面的path會(huì)替換掉路由棧里最后一個(gè)路由
路由跳轉(zhuǎn)開啟replace模式损敷,默認(rèn)是push模式
<Link to={`/home/message/detail/${i.id}/${i.title}`} replace={true} children={i.title} />
編程式路由
通過按鈕觸發(fā)方法葫笼,方法里進(jìn)行路由跳轉(zhuǎn)
<button onClick={() => this.pushShow(i)}>Push查看</button>
<button onClick={() => this.replaceShow(i)}>Replace查看</button>
注冊路由
接收params參數(shù)
<Route path="/home/message/detail/:id/:title" component={Detail} />
search參數(shù)無需聲明接收,正常注冊路由即可
<Route path="/home/message/detail" component={Detail} />
state參數(shù)無需聲明接收拗馒,正常注冊路由即可
<Route path="/home/message/detail" component={Detail} />
跳轉(zhuǎn)路由
replaceShow = (i) =>{
replace跳轉(zhuǎn)+攜帶params參數(shù)
this.props.history.replace(`/home/message/detail/${i.id}/${i.title}`)
replace跳轉(zhuǎn)+攜帶search參數(shù)
this.props.history.replace(`/home/message/detail?id=${i.id}&title=${i.title}`)
replace跳轉(zhuǎn)+攜帶state參數(shù)
this.props.history.replace(`/home/message/detail`,{...i})
}
pushShow = (i) =>{
push跳轉(zhuǎn)+攜帶params參數(shù)
this.props.history.push(`/home/message/detail/${i.id}/${i.title}`)
push跳轉(zhuǎn)+攜帶search參數(shù)
this.props.history.push(`/home/message/detail?id=${i.id}&title=${i.title}`)
push跳轉(zhuǎn)+攜帶state參數(shù)
this.props.history.push(`/home/message/detail`,{...i})
}
路由組件接受路由參數(shù)
接收params參數(shù)
const {id, title} = this.props.match.params;
接收search參數(shù)
import qs from "querystring";
const {id, title} = qs.parse((this.props.location.search).slice(1));
接收state參數(shù)
const {id, title} = this.props.location.state || {};