Route 是 React Router中用於配置路由信息的組件,每當有一個組件需要根據 URL 決定是否渲染時,就需要創建一個 Route。
react-router 中的很多特性都與 React 保持了一致,比如它的聲明式組件、組件嵌套,當然也包括 React 的狀態機特性。
1.path
每個Route都需要一個path屬性,path屬性是一個url,當URL匹配一個Route時,這個Route中定義的組件就會被渲染出來。
2.Route渲染組間的方式
(1)Component
component的值是一個組件,當URL和Route匹配時,Component屬性定義的組件就會被渲染。
<Route path="/mycom" component={MyCom} >
(2)Render
Render 值是一個函數,這個函數返回一個React元素。這種方式方便地為待渲染的組件傳遞額外的屬性。
<Route path=‘/mycom’ render={(props) => { <MyCom {…props} data={extraProps} /> //MyCom 組件接收了一個額外的data屬性 }}> </Route>
(3)children
Children的值也是一個函數,函數返回要渲染的React元素。與前面不同是,無論是否匹配成功,children返回的組件都會被渲染。匹配不成功時,match屬性為null。
<Route path="/myCom" render={(props) => { <div className={props.match ? 'active' : ''}> <Foo {…props} data={extraProps} /> </div> }} </Route>
如果Route匹配當前URL,待渲染元素的根節點div的class將設置成active.
3.多級路由
在路由里面繼續寫路由,掛載組件,就可以實現多級路由。路由嵌套實現。
<Route path=‘/myCom’ component={myCom}>
<Route path=‘/myCom/sonCom’ component={SonCom}></Route>
</Route>
如果多級路由嵌套的層次太深,那我們寫子路由的path就會特別麻煩,所以可以這樣:
<Route path=‘/mycom’ render={(props) => {
<Route path={`${props.match.path}/sonCom`} component={SonCom} /> }}>
</Route>
Match是從props解構出來,match.path就是我們當前這個路由的路徑,這樣不管嵌套多深,都可以寫上一級的路由
4.動態傳參
/foodlist/:id,傳過去的值就在路由掛載組件的props中,props里有個match, match中有個params, 注意:props只在路由掛載的組件才有
<Route path=‘/foodlist/:id’ component={MyCom} />
MyCom 組件的props中就可以獲取到id
可以在一個組件中用 this.props.history.push(“/path”, {name: “hellow”}), 來進行傳參,傳過去的值在props.location.state中
5.withRouter
一個典型的高階組件,如果我們既想實現點擊跳轉,又不想用Link的a標簽,我們可以用withRouter給我們吐出來一個實現點擊跳轉路由的組件。 Eg.
import { withRouter } from 'react-router-dom’; //使用自定義的組件: <CustomNavLink to="/food">food</CustomNavLink> <CustomNavLink to="/wiki">wiki</CustomNavLink> <CustomNavLink to="/profile">profile</CustomNavLink> //給自定義組件實現點擊功能: const CustomNavLink = withRouter(class EnhenceCustomNavLink extends Component { render () { return ( <li onClick={this.goto.bind(this)}> { this.props.location.pathname === this.props.to ? '>' + this.props.children : this.props.children } </li> ) } goto () { this.props.history.push(this.props.to) } })
假如你的組件沒有路由信息,你可以使用withRouter(component)將這個組件包起來,props里面就有路由信息了。
這里我們順便了解下前端路由的兩種模式:Hash模式和History模式
1、Hash 模式:
這里的 hash 就是指 url 尾巴后的 # 號以及后面的字符。Hash 也稱作錨點,用來做頁面的定位,可以使對應的id的元素顯示在可視區域內。
Hash值的變化不會導致瀏覽器向服務器發出請求,而且hash改變會觸發hashchange事件,瀏覽器的前進和后退也能對其進行控制,在html5的history出現前,基本就是使用hash來實現前段路由的。
window.location.hsah = 'qq' //設置url的hash,會在當前url后加上#qq var hash = window.location.hsah //qq Window.addEventListener('hashchange', function() { //監聽hash變化,點擊瀏覽器的前進后退會觸發 )
2, History模式
已經有 hash 模式了,而且 hash 能兼容到IE8, history 只能兼容到 IE10,為什么還要搞個 history 呢?
首先,hash 本來是拿來做頁面定位的,如果拿來做路由的話,原來的錨點功能就不能用了。其次,hash 的傳參是基於 url 的,如果要傳遞復雜的數據,會有體積的限制,而 history 模式不僅可以在url里放參數,還可以將數據存放在一個特定的對象中。
window.history.pushState(state, title, url) // state:需要保存的數據,這個數據在觸發popstate事件時,可以在event.state里獲取 // title:標題,基本沒用,一般傳 null // url:設定新的歷史記錄的 url。新的 url 與當前 url 的 origin 必須是一樣的,否則會拋出錯誤。url可以是絕對路徑,也可以是相對路徑。 /*如 當前url是 https://www.baidu.com/a/,執行history.pushState(null, null, './qq/'),則變成 https://www.baidu.com/a/qq/,執行history.pushState(null, null, '/qq/'),則變成 https://www.baidu.com/qq/ */ window.history.replaceState(state, title, url) // 與 pushState 基本相同,但這是修改當前歷史記錄,而 pushState 是創建新的歷史記錄 window.addEventListener(“popstate”, funbction(){ // 監聽瀏覽器前進后退事件,pushState 與 replaceState 方法不會觸發 }); window.history.back() // 后退 window.history.forward()// 前進 window.history.go(1) //前進一步,-2為后退兩步,window.history.length可以查看當前歷史堆棧中頁面的數量
history 模式改變 url 的方式會導致瀏覽器向服務器發送請求,需要在服務器端做處理:如果匹配不到任何靜態資源,則應該始終返回同一個 html 頁面。
我們再順便了解下:用戶訪問的URL后面加入# 號的知識
1. #號的含義:
#號代表網頁中的一個位置,# 號后面的內容就是該位置的一個標記,eg.
http://www.example.com/index.html#print
訪問該地址,瀏覽器頁面會自動滾動到print 位置,print顯示在可視區域
//為頁面指定位置的有兩種方式: (1)加錨點 <a name=“print”></a> (2)<div id=“print”></div>
2.Http請求不包括#部分
比如訪問上面的鏈接,實際發出的請求是:
GET /index.html HTTP/1.1
Host: www.example.com
#號后面的任何字符,都會被解析為位置標志符,比如:
http://www.example.com/?color=#fff
實際發出的請求是:
GET /?color= HTTP/1.1
Host: www.example.com
這並不是我們所期望的,可以對#號轉義 #轉為23%
http://www.example.com/?color=23%fff
3.改變網頁的#號部分,不會觸發網頁的重載
http://www.example/com/index.html#location1 http://www.example.com/index.html#location2 //改變#號后面的內容,不會重新觸發服務器的請求,也就是#號后面的內容對服務器端沒影響
4.改變#號后面的內容,可以修改瀏覽器的訪問歷史
每一次改變#后的部分,都會在瀏覽器的訪問歷史中增加一個記錄,使用"后退"按鈕,就可以回到上一個位置。
5.window.location.hash 可以讀到#號后面的內容
來判斷網頁是否發生了變化,給window.location.hash賦值時,就是增加了一條瀏覽器的歷史訪問記錄
6. onhashchange 是HTML5增加的可以監聽hash改變的接口:
window.onhashchange = func; <body onhashchange="func();"> window.addEventListener("hashchange", func, false);
對於不支持onhashchange的瀏覽器,可以用setInterval監控location.hash的變化。
7.Google抓取#的機制
默認情況下,Google的網絡蜘蛛忽視URL的#部分。
如果你希望Ajax生成的內容被瀏覽引擎讀取,那么URL中可以使用"#!",Google會自動將其后面的內容轉成查詢字符串_escaped_fragment_的值。