1. 后端路由與前端路由
多頁(yè)面應(yīng)用和后端路由
在傳統(tǒng)的Web應(yīng)用中,瀏覽器根據(jù)地址欄的URL向服務(wù)器發(fā)送一個(gè)HTTP請(qǐng)求,服務(wù)器根據(jù)URL返回一個(gè)HTML頁(yè)面。這種情況下黔寇,一個(gè)URL對(duì)應(yīng)一個(gè)HTML頁(yè)面,一個(gè)Web應(yīng)用包含很多HTML頁(yè)面斩萌,這樣的應(yīng)用就是 多頁(yè)面應(yīng)用缝裤;在多頁(yè)面應(yīng)用中屏轰,頁(yè)面路由的控制由服務(wù)器端負(fù)責(zé),這種路由方式稱為 后端路由憋飞。
單頁(yè)面應(yīng)用和前端路由
URL的變化可以引起頁(yè)面內(nèi)容的變化霎苗,但不會(huì)向服務(wù)器發(fā)送新的請(qǐng)求,頁(yè)面的內(nèi)容也會(huì)發(fā)生變化,但這只是邏輯上的頁(yè)面變化榛做,無(wú)論URL如何變化唁盏,對(duì)應(yīng)的HTML文件都是同一個(gè),這樣叫做 單頁(yè)面應(yīng)用. 在單頁(yè)面應(yīng)用中,URL發(fā)生變化并不會(huì)向服務(wù)器發(fā)送新的請(qǐng)求检眯,所以“邏輯頁(yè)面”(這個(gè)名稱用來(lái)和真實(shí)的HTML頁(yè)面區(qū)分)的路由只能由前端負(fù)責(zé)厘擂,這種路由方式稱為 前端路由。
React Router就是一種前端路由的實(shí)現(xiàn)方式轰传。通過(guò)使用React Router可以讓W(xué)eb應(yīng)用根據(jù)不同的URL渲染不同的組件,這樣的組件渲染方式可以解決更加復(fù)雜的業(yè)務(wù)場(chǎng)景瘪撇。例如获茬,當(dāng)URL的pathname為/list時(shí),頁(yè)面會(huì)渲染一個(gè)列表組件倔既,當(dāng)點(diǎn)擊列表中的一項(xiàng)時(shí)恕曲,pathname更改為/item/:id(id為參數(shù)),舊的列表組件會(huì)被卸載渤涌,取而代之的是一個(gè)新的單一項(xiàng)的詳情組件佩谣。
2. 安裝路由
npm install react-router-dom
React Router包含3個(gè)庫(kù):react-router、react-router-dom和react-router-native实蓬。
react-router提供最基本的路由功能茸俭,實(shí)際使用時(shí),我們不會(huì)直接安裝react-router.
而是根據(jù)應(yīng)用運(yùn)行的環(huán)境選擇安裝react-router-dom(在瀏覽器中使用)或react-router-native(在react-native中使用)安皱。
react-router-dom和react-router-native都依賴于react-router调鬓,所以在安裝時(shí),react-router也會(huì)自動(dòng)安裝酌伊。
所以我們只需要安裝 react-router-dom
3. 引入路由
引入路由
// 哈希模式
import {HashRouter as Router, Link, Route} from 'react-router-dom'
//或者
// history模式
import {BrowserRouter as Router, Link, Route} from 'react-router-dom'
// ReactRouter三大組件
// Router 所有路由組件的根組件, 包裹路由規(guī)則的最外層容器
// Route 路由規(guī)則匹配組件, 顯示當(dāng)前規(guī)則對(duì)應(yīng)的組件
// Link 路由跳轉(zhuǎn)組件
4. HashRouter和BrowserRouter
Router可以理解成路由器腾窝,一個(gè)應(yīng)用中只需要一個(gè)Router實(shí)例, React Router中的其他組件必須作為Router組件的后代組件使用。但Router中只能有唯一的一個(gè)子元素
Router會(huì)創(chuàng)建一個(gè)history對(duì)象居砖,history用來(lái)跟蹤URL虹脯,當(dāng)URL發(fā)生變化時(shí),Router的后代組件會(huì)重新渲染奏候。React Router中提供的其他組件可以通過(guò)context獲取history對(duì)象
BrowserRouter使用HTML 5的history API(pushState循集、replaceState等)實(shí)現(xiàn)應(yīng)用的UI和URL的同步
BrowserRouter創(chuàng)建的URL形式如下:http://example.com/some/path
使用BrowserRouter時(shí),一般還需要對(duì)服務(wù)器進(jìn)行配置蔗草,讓服務(wù)器能正確地處理所有可能的URL暇榴。例如厚棵,當(dāng)瀏覽器發(fā)送http://example.com/some/path
和http://example.com/some/path2
兩個(gè)請(qǐng)求時(shí),服務(wù)器需要能返回正確的HTML頁(yè)面(也就是單頁(yè)面應(yīng)用中唯一的HTML頁(yè)面)
HashRouter使用URL的hash實(shí)現(xiàn)應(yīng)用的UI和URL的同步蔼紧。
HashRouter創(chuàng)建的URL形式如下:http://example.com/#/some/path
使用HashRouter則不存在這個(gè)問(wèn)題婆硬,因?yàn)閔ash部分的內(nèi)容會(huì)被服務(wù)器自動(dòng)忽略荧关,真正有效的信息是hash前面的部分叁温,而對(duì)于單頁(yè)面應(yīng)用來(lái)說(shuō)鲜结,這部分內(nèi)容是固定的
5. Route
Route是匹配組件, 常用的屬性有path和component.
Route的exact和strict修飾符
exact 精確匹配 默認(rèn)為false遇汞,如果為true時(shí)熊楼,需要和路由相同時(shí)才能匹配通惫。
false 路由:'/Home' url '/Home' 和 '/Home/myPage' 都會(huì)匹配
true 路由:'/Home' 只有url '/Home'才匹配, url '/Home/myPage' 不匹配
strict 斜杠敏感 默認(rèn)為false叉瘩,如果為true時(shí)教硫,url對(duì)斜杠敏感
false url '/Home' 和 url '/Home/' 視為相同的url
true url '/Home' 和 url '/Home/' 視為不相同的url
6. Link
Link是跳轉(zhuǎn)組件, 常用的屬性是 to
to屬性值可是字符串
也可以是對(duì)象: 這個(gè)對(duì)象包含 pathname逻卖、search宋列、hash、state四個(gè)屬性
例如:
let toArgs = {
// 跳轉(zhuǎn)的路徑
pathname: '/User',
// get的入?yún)? search: '?user=admin',
// hash的值
hash: '#abc',
// 組件的值
state: {fromHome: true}
}
組件中的 this.props.location
存放著這個(gè)入?yún)?br>
在組件中查看這個(gè)入?yún)?
this.props.location.state.fromHome;
7. switch
當(dāng) Router中的Route有多個(gè)符合匹配條件時(shí), 如果不添加switch, 所有匹配的組件都會(huì)渲染
當(dāng) 這些Route被 switch包裹時(shí), 當(dāng)?shù)谝粋€(gè)符合匹配條件的組件渲染后, 不再向下匹配. (保證只顯示第一個(gè)匹配的組件)
8. history
路由頁(yè)面跳轉(zhuǎn)
history.push(path,[state])
history.replace(path,[state])
區(qū)別:
push是把新頁(yè)面放入棧中, 保留上一個(gè)頁(yè)面的歷史記錄, 這樣返回還可以回到上一個(gè)頁(yè)面
replace是把新頁(yè)面替換上一個(gè)頁(yè)面在棧中的歷史記錄, 這樣返回的時(shí)候會(huì)回到上上個(gè)頁(yè)面
現(xiàn)在有三個(gè)頁(yè)面 a->b->c
b跳轉(zhuǎn)c的時(shí)候, 如果使用push到c頁(yè)面,在c頁(yè)面點(diǎn)擊返回回到b頁(yè)面
b跳轉(zhuǎn)c的時(shí)候, 如果使用replace到c頁(yè)面,在c頁(yè)面點(diǎn)擊返回回到a頁(yè)面
// 向前或向后跳轉(zhuǎn)n個(gè)頁(yè)面, 正數(shù)為前進(jìn), 負(fù)數(shù)為后退
this.props.history.go(n)
// 前進(jìn)
this.props.history.go(1);
//或者
this.props.history.goForward();
// 回退
this.props.history.go(-1);
//或者
this.props.history.goBack();
9. 動(dòng)態(tài)路由
Route這樣寫(xiě) /path/:動(dòng)態(tài)參數(shù) 如:
<Route path='/User/:user' component={User}></Route>
Link這樣寫(xiě) /path/具體的參數(shù) 如:
<Link className='linkC' to='/User/admin'>用戶</Link>
生產(chǎn)的url是 #/User/admin
組件的this.props.match.params
存放這個(gè)動(dòng)態(tài)參數(shù)
在組件中查看這個(gè)動(dòng)態(tài)參數(shù)
this.props.match.params.user;
10. Redirect重定向
待補(bǔ)充...
11. 組件被加入路由后, 組件的this.props新增屬性
this.props.history
this.props.history提供了push, replace, go, goBack, goForward等方法
// this.props.history.go(n)
// 向前或向后跳轉(zhuǎn)n個(gè)頁(yè)面, 正數(shù)為前進(jìn), 負(fù)數(shù)為后退
// 前進(jìn)
this.props.history.go(1);
this.props.history.goForward();
// 回退
this.props.history.go(-1);
this.props.history.goBack();
this.props.location
this.props.location存放的是Link to屬性傳入的對(duì)象,包括pathname评也、search炼杖、hash、state四個(gè)屬性
let toArgs = {
// 跳轉(zhuǎn)的路徑
pathname: '/User',
// get的入?yún)? search: '?user=admin',
// hash的值
hash: '#abc',
// 組件的值
state: {fromHome: true}
}
<Link className='linkC' to={toArgs}>登錄</Link>
// 組件中的 this.props.location 存放著這個(gè)入?yún)?// 在組件中查看這個(gè)入?yún)?this.props.location.state.fromHome;
this.props.match
this.props.match.params存放著動(dòng)態(tài)路由的動(dòng)態(tài)參數(shù)
// Route這樣寫(xiě) /path/:動(dòng)態(tài)參數(shù) 如:
<Route path='/User/:user' component={User}></Route>
// Link這樣寫(xiě) /path/具體的參數(shù) 如:
<Link className='linkC' to='/User/admin'>用戶</Link>
// 訪問(wèn)這個(gè)屬性:
this.props.match.params.user;
11. window.location
頁(yè)面刷新時(shí), 如果想要訪問(wèn)到當(dāng)前頁(yè)面的哈希路徑, 以此來(lái)作為判斷條件做一些預(yù)處理, 在react的生命周期函數(shù)UNSAFE_componentWillMount執(zhí)行時(shí), props屬性還沒(méi)有被注入數(shù)據(jù)的情況, 可以通過(guò)window.location來(lái)訪問(wèn)到hash路徑
UNSAFE_componentWillMount(){
/* 每次刷新頁(yè)面時(shí),可以通過(guò)window.location獲取到當(dāng)前的hash路徑, 以此來(lái)獲取一下當(dāng)前頁(yè)等信息.
然后定位對(duì)應(yīng)的位置等操作. 因?yàn)轫?yè)面剛刷新, 在willMount的時(shí)候我們還無(wú)法訪問(wèn)props.
*/
console.log('頁(yè)面刷新時(shí)會(huì)調(diào)用這個(gè)方法. 來(lái)查看一下刷新時(shí)的hash路由');
//可以看到這時(shí)候props還沒(méi)有數(shù)據(jù), 如果想拿到哈希路徑, 就需要訪問(wèn)window.location
console.log('this.props',this.props);
console.log(window.location.hash);
console.log(window.location.hash.split('/'));
console.log(window.location.hash.split('/')[1]);
}