手挽手带你学React:三档 React-router4.x的使用
手挽手帶你學React入門三檔,帶你學會使用Reacr-router4.x,開始創建屬于你的React項目
什么是React-router
React Router 是一個基于 React 之上的強大路由庫,它可以讓你向應用中快速地添加視圖和數據流,同時保持頁面與 URL 間的同步。通俗一點就是,它幫助我們的程序在不同的url展示不同的內容。
為什么要用React-router
我們開發的時候,不可能所有的東西都展示在一張頁面上,在業務場景的要求下,我們要根據不同的URL或者不同的哈希來展示不同的組件,這個我們可以稱它為路由。在我們不使用React-router的時候,我們如何去做路由呢?
我在這里給大家舉個例子,不使用React-router,來實現一個簡單路由。
// App.js import React,{Component} from 'react' export default class App extends Component {constructor(){super()// 我們在App.js內部來渲染不同的組件 我們這里采用哈希路由的方式,鑒于React的渲染機制,我們需要把值綁定進入state內部。this.state={route:window.location.hash.substr(1)}}componentDidMount() {// 這里我們通過監聽的方式來監聽哈希的變化,并且來更新state促進視圖更新window.addEventListener('hashchange', () => {console.log(window.location.hash.substr(1))this.setState({route: window.location.hash.substr(1)})})}render() {//在這里我們定義一個RouterView 所有的變化后的組件都會丟到這個RouterView中let RouterView = Appswitch (this.state.route) {case '/children1':RouterView = Childrenbreak;case '/children2':RouterView = ChildrenTwobreak;default:RouterView = Homebreak;}return (<div> <h1>App</h1><ul><li><a href="#/children1">children1</a></li> {/* 點擊更改哈希值 這里觸發我們的監聽 然后修改state來觸發組件的重新傳染 */}<li><a href="#/children2">children2</a></li></ul><RouterView/></div>)} }// 為了展示效果定義子組件一class Children extends Component{constructor(){super()this.state={}}render(){return(<div><h1>我是子組件1</h1></div>)} }// 為了展示效果定義子組件二class ChildrenTwo extends Component{constructor(){super()this.state={}}render(){return(<div><h1>我是子組件2</h1></div>)} } // 為了展示效果定義Home組件 class Home extends Component{constructor(){super()}render(){return(<h1>我是Home</h1>)} }這樣我們通過監聽哈希變化的方式實現了我們的第一個簡單路由,是不是對于路由的原理有了那么一丟丟的認識呢?接下來我們想象一個場景,這么一個路由出現了/children1/user/about/1,看到這里是不是覺得,用switch case已經蒙B了?我們接下來就要使用到React-router了,這個東西可不需要我們自己去寫一大串的switch case了,并且性能啊,整潔度啊等等等方面都比我們自己寫的好多了!
React-router 初體驗
首先我們在React項目文件目錄下執行
npm install react-router-dom --save npm install react-router --save要想體驗一個新的東西,當然是要拿自己開刀 我們改進上面我們寫過的組件
// App.js import React,{Component} from 'react' // 首先我們需要導入一些組件... import { HashRouter as Router, Route, Link } from "react-router-dom"; // 這里有BrowserRouter 和 HashRouter 兩種模式 我比較推薦HashRouter來學習 BrowserRouter需要后端配合 單獨前端設置 刷新會出現404 // 然后我們把App組件整理干凈,大概成這個樣子 export default class App extends Component {constructor(){super()this.state={}}render() {return (<Router><div><h1>App</h1><ul><li> <Link to="/">Home</Link></li> <li><Link to="/children1/">children1</Link></li><li><Link to="/children2/">children2</Link></li></ul><Route exact path="/" component={Home} /><Route path="/children1" component={Children} /><Route path="/children2" component={ChildrenTwo} /></div></Router>)} }// 為了展示效果定義子組件一 class Children extends Component{constructor(){super()this.state={}}render(){return(<div><h1>我是子組件1</h1></div>)} } // 為了展示效果定義子組件二 class ChildrenTwo extends Component{constructor(){super()this.state={}}render(){return(<div><h1>我是子組件2</h1></div>)} } // 為了展示效果定義Home組件 class Home extends Component{constructor(){super()}render(){return(<h1>我是Home</h1>)} }這里我們就完成了React-router4.X的初步體驗,怎么樣~我給大家的第一次的感覺還可以吧~
基本組件
Routers
在React-router4.0中,Routers有兩個表現方式 <BrowserRouter> 和 <HashRouter> 這兩個標簽都將會給你創建一個專門的history對象,BrowserRouter的表現模式需要搭配一個可以響應請求的服務器。HashRouter是靜態文件服務器,我們本地開發的時候,建議使用HashRouter。這里需要注意一下,BrowserRouter和 HashRouter標簽下面,只允許存在一個標簽 具體寫法如下
Route
注意,最外層的是Router 這里是 Route 這是我們的路由匹配組件,它有兩個 Route和Switch
Route 組件擁有多個屬性,這在我們后期的路由傳參中將會用到。這里我們需要簡單了解幾個屬性 path component exact strict
path 是我們匹配的地址,當地址匹配的時候 我們才會去渲染 component內的組件內容
path 后面如果書寫模式帶了 /: 這樣的內容,那么這里將會成為占位符 我們可以利用占位符來取到對應路徑的參數 使用 this.props.match.params+占位符的名字 即可拿到
exact 屬性來規定我們是否嚴格匹配
strict 則是嚴格匹配模式 我們規定的路徑使用/one/來書寫 如果沒有完全匹配 /one/ 則不會展示
同時React-router給我們提供了一個Switch標簽 在這個標簽內 我們只會渲染一個Route 并且使第一個符合條件的Route 這是什么意思呢?我們來看代碼
<Route path="/about" component={About} /> <Route path="/:User" component={User} /> <Route path="/" component={Home} /> <Route component={NoMatch} />在這樣的路由下 我們匹配/about 會發現 所有的路由都可以匹配到并且渲染了出來,這肯定不是我們想要的結果 于是我們給它嵌套一個 Switch
<Switch><Route path="/about" component={About} /><Route path="/:User" component={User} /><Route path="/" component={Home} /><Route component={NoMatch} /> </Switch>這時候我們就只會匹配到第一個/about,僅僅渲染About,大家根據實際需求去決定是否嵌套Switch使用
Link和NavLink
Link 主要api是to,to可以接受string或者一個object,來控制url。我們代碼里看看書寫方法
<Link to='/one/' /> // 這就是路由到one 搭配Router使用 當然我們可以使用一個對象<Link to={{pathname:'/one',search:'?name=qm',hash:'#two',state:{myName:'qimiao'}}} />// 這樣我們點擊link不僅可以到one 還可以傳遞一些參數NavLink 它可以為當前選中的路由設置類名、樣式以及回調函數等。使用如下
<NavLink exact activeClassName='navLink' to='/one/' /> // 這就是路由到one 搭配Router使用 當然我們可以使用一個對象<NavLink exact activeClassName='navLink' to={{pathname:'/one',search:'?name=qm',hash:'#two',state:{myName:'qimiao'}}} />// 這里的exact 同樣是嚴格比配模式 同Route// 這樣我們可以為當前選中的路由設置樣式了子路由的書寫
在react-router4之前的版本,子路由通過路由嵌套就可以實現了,但是這一個方法到了React-router4中就行不通了
先來一個之前的寫法,當然也是錯誤示例
export default class App extends Component {constructor(){super()this.state={}}render() {return (<Router><div><h1>App</h1><ul><li> <Link to="/home">Home</Link></li> <li><Link to="/children1/">children1</Link></li><li><Link to="/children2/">children2</Link></li></ul><Route path="/home" component={Home} ><Route path="children1" component={Children} /><Route path="children2" component={ChildrenTwo} />{/*在4.0以后的版本這樣都會報錯 那么我們應該怎么寫呢*/}</Route></div></Router>)} }在react-router4.x版本中 我們子路由必須要在子組件內部了
export default class App extends Component {constructor(){super()this.state={}}render() {return (<Router><div><h1>App</h1><ul><li> <Link to="/home">Home</Link></li> {/* 同樣 這兩個link讓他們轉移到Home中 我們的home組件就變成了下面的樣子 */}</ul><Route path="/home" component={Home} >{/*<Route path="children1" component={Children} />*/} {/*<Route path="children2" component={ChildrenTwo} />*/} {/*先把這里注釋掉 然后我們來到Home組件內*/}</Route></div></Router>)} }// home內部用{this.props.match.url+子路由路徑}來獲取當前的路徑并且加上我們要路由到的位置來進行路由匹配和路徑跳轉匹配 這樣書寫 Children和ChildrenTwo就是home的子路由了 class Home extends Component{constructor(){super()}render(){return(<div><h1>我是Home</h1><li><Link to={`${this.props.match.url}/children1`}>children1</Link></li><li><Link to={`${this.props.match.url}/children2`}>children2</Link></li><Route path={`${this.props.match.url}/children1`} component={Children} /><Route path={`${this.props.match.url}/children2`} component={ChildrenTwo} /> </div>)} }路由跳轉
聲明式跳轉上面已經說過了 Link和NavLink 兩個標簽就可以滿足了 我們主要說一下js跳轉
在4.0剛剛發布的時候 this.props.history.push('路徑')這個方法已經行不通了,不過值得慶幸的是,我現在所使用的4.3.1版本又可以使用這個方法來進行js路由跳轉了。
我們用home組件來舉個例子
class Home extends Component{constructor(){super()}toPath=(home)=>{console.log(123)this.props.history.push({ //我們把要傳參的東西都放在push對象內了pathname:home, //我們要到達哪個路由search:"?a=1", //明文傳參的模式query:{'type':'type'}, //query對象傳參state:{ //state對象傳參b:456}})// this.props.history.push('/123')}render(){return(<div><h1 onClick={()=>{this.toPath(`${this.props.match.url}/children1/123`)}}>我是Home</h1><li><Link to={`${this.props.match.url}/children1`}>children1</Link></li><li><Link to={`${this.props.match.url}/children2`}>children2</Link></li><Route path={`${this.props.match.url}/children1/:id`} component={Children} /><Route path={`${this.props.match.url}/children2`} component={ChildrenTwo} /> </div>)} }/*相應的 我們在Children 組件里面有對應的方法來獲取參數。*/class Children extends Component{constructor(){super()this.state={}}render(){console.log(this.props.match.params.id) //這種是通過路徑上面的:id傳過來的參數console.log(this.props.location.query) //這是通過push的參數對象中的query傳過來的 和vue的query有區別 它不在地址欄 刷新丟失console.log(this.props.location.state) //這是通過push的參數對象中的state傳過來的 它不在地址欄 刷新丟失console.log(this.props.location.search) //暴露在地址欄,需要自行處理獲取數據return(<div><h1>我是子組件1 </h1></div>)} }總結
這一期我們主要還是講了react-router4.x的基礎使用和傳參方法,react-router4.x坑比較多,不過使用熟練了會讓你感覺很爽,大家不要吝嗇自己的時間多多學習,博客開通了注冊投稿功能,如果大家有好的學習文章,經典總結,可以投稿,可以掃碼加我微信申請專欄~感謝大家的閱讀和觀看。
視頻制作中
總結
以上是生活随笔為你收集整理的手挽手带你学React:三档 React-router4.x的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Go并发编程之美-读写锁
- 下一篇: weekly 2019-02-15