1引入react-router-dom包(前面屬講解部分,可以直接拉至下方看demo)
npm install react-router-dom --save
或者 yarn add react-router-dom
2 創建並暴露router.js文件,並在index.js里引入,之后在其他頁面使用Link便可。頁面模板如下
這是index.js頁面
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import Router from './router.js';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<Router/>, document.getElementById('root')); /* 這里引入的是Router而不是router.js頁面暴露出的IRouter */
serviceWorker.unregister();
這是router.js頁面
import React from 'react';
import {BrowserRouter,Route,Switch} from 'react-router-dom';
/* 引入BrowserRouter,Route,Switch等 */
import MissionCowry from './mission-cowry/mission-cowry.js';
/* 引入父頁面組件——子頁面組件的內容會渲染到父頁面組件里,子頁面組件內容即Link之后的{this.props.children} */
import MissionManage from './mission-cowry/mission-manage/mission-manage.js';
/* 引入子頁面組件 */
import PosterManage from './mission-cowry/poster-manage/poster-manage.js';
import PosterAdd from './mission-cowry/poster-manage/poster-add.js';
import ActivityData from './mission-cowry/activity-data/activity-data.js';
import AllRecord from './mission-cowry/score-shop/all-record.js';
import CommodityManage from './mission-cowry/score-shop/commodity-manage.js';
export default class IRouter extends React.Component {
//其實這里Irouter,Erouter,Crouter命名是比較隨意,只要不用Router命名就行
render(){
return(
//---布置路由---
<BrowserRouter> //最外層用BrowserRouter包裹,有時也可以是HashRouter等
<MissionCowry> //外層用父頁面組件包裹
<Switch> //Switch即從上往下查找,找到了即終止查找
<Route path='/mission-manage/mission-manage.js' component={MissionManage} />
//path地址要從父頁面(./mission-cowry)的下一層目錄開始 ,有時要帶js后綴有時反而就不能帶,這里有點不懂。
<Route exact={true} path='/poster-manage/poster-manage.js' component={PosterManage} /> //exact="true" 精准跳轉
<Route path='/poster-manage/poster-add.js' component={PosterAdd} />
<Route path='/activity-data/activity-data.js' component={ActivityData} />
<Route path='/score-shop/all-record.js' component={AllRecord} />
<Route path='/score-shop/commodity-manage.js' component={CommodityManage} />
</Switch>
</MissionCowry>
</BrowserRouter>
);
}
}
這是導航菜單頁面,或者說跳轉按鈕所在的頁面
import React from 'react';
import '../comp.less';
import {Link} from 'react-router-dom'; /* 這里要引入Link */
import {Layout,Menu,Breadcrumb,Icon,Divider} from 'antd';
const {SubMenu} = Menu;
const {Header,Content,Sider} = Layout;
export default class MissionCowry extends React.Component{
render(){
return(
<div className="LinkDemo">
<Layout>
<Sider collapsible collapsed={this.state.collapsed} onCollapse={this.onCollapse} className="mainsider">
<Menu theme="dark" defaultSelectedKeys={['sub2-1']} defaultOpenKeys={["sub2"]} mode="inline">
<Menu.Item key="1">
<Link to="/poster-manage/poster-manage.js"><span>海報管理</span></Link>
</Menu.Item>
<Menu.Item key="2">
<Link to="/mission-manage/mission-manage.js"><span>任務管理</span></Link>
</Menu.Item>
<SubMenu key="sub1" title={<span><Icon type="paper-clip" /><span><Link></Link>積分商城</span></span>}>
<Menu.Item key="sub1-1"><Link to="/score-shop/commodity-manage.js">商品管理</Link></Menu.Item>
<Menu.Item key="sub1-2"><Link to="/score-shop/realthings-record.js">實物記錄</Link></Menu.Item>
</SubMenu>
<Menu.Item key="3">
<Link to="/activity-data/activity-data.js"><span>活動數據</span></Link>
</Menu.Item>
</Menu>
</Sider>
<Layout>
<Content className="maincontent">
{this.props.children}
//這是路由導入的子頁面組件的內容,這里把它放在Content里呈現
</Content>
</Layout>
</Layout>
</div>
);
}
}
其他頁面需要路由跳轉的話
先將需要跳轉到的頁面在router.js里導入並布置路由
再在當前頁面使用Link寫一下跳轉格式就OK了
如:點擊"添加商品"跳轉到商品添加頁
<Link to="/commodity-manage/commodity-add.js"><Button ><span>添加海報</span></Button></Link>
嵌套路由怎么理解?怎么使用?參考以下幾個頁面
——————————————————————————————————————————————
router.js頁面
import React from 'react'
import {HashRouter as Router,Route,LinK} from 'react-router-dom'
import Main from './Main'
import About from './../route1/about'
import Topic from './../route1/topic'
import Home from './Home'
export default class IRouter extends React.Component{
render(){
return (
<Router>
<Home>
<Route path="/main" render={()=>
<Main>
<Route path="/main/a" component={About}></Route>
</Main>
}></Route>
<Route path="/about" component={About}></Route>
<Route path="/topics" component={Topic}></Route>
</Home>
</Router>
);
}
}
——————————————————————————————————————————————
Main.js頁面
import React from 'react'
import { Link } from 'react-router-dom'
export default class Main extends React.Component {
render() {
return (
<div>
this is main page.
<Link to="/main/a">嵌套路由</Link>
<hr/>
{this.props.children} //記住嵌套路由也一定別忘記了this.props.children
</div>
);
}
}
——————————————————————————————————————————————
Home.js頁面
import React from 'react'
import { Link } from 'react-router-dom'
export default class Home extends React.Component {
render() {
return (
<div>
<ul>
<li>
<Link to="/main">Home1</Link>
</li>
<li>
<Link to="/about">About1</Link>
</li>
<li>
<Link to="/topics">Topics1</Link>
</li>
</ul>
<hr />
{this.props.children}
</div>
);
}
}
嵌套路由樣式共用
嵌套路由,如果在父頁面中引入子頁面組件。那么子頁面組件也就是父頁面的一部分了,此時子頁面組件是享有父頁面的css樣式的
例:
1 父頁面引入了子頁面組件
2 父頁面div定義了className="header",子頁面組件div定義了className="header"
3 父頁面引入了comp.less,子頁面未引入
4 comp.less里定義了.header{width:200px; height:100px; backgoundcolor:red;}
4 該樣式在子頁面組件里同樣生效
注意:這個可能會帶來樣式沖突問題,所以在定義父頁面以及子頁面className的時候,要盡量保證命名不要重復
路由目錄層級涉及的路徑問題(path,Link)
src
|__demo
| |__subdemo1.js
| |__subdemo2.js
| |__subdemo1-sub1.js
| |__subdemo1-sub2.js
|__router.js
如目錄所示,subdemo1-sub1.js和subdemo1-sub2.js是subdemo1.js的子頁面組件。
但是!!它們卻放在了同一文件夾(demo)下,那路由路徑怎么解決呢
以下是router.js里的部分代碼
import SubDemo1 from './demo/subdemo1.js' //看到沒有,import是按照文件所在路徑正常引入的,這些文件都在demo文件夾下
import SubDemo1Sub1 from './demo/subdemo1-sub1.js'
import SubDemo1Sub1 from './demo/subdemo1-sub2.js'
<Link to="/demo/subdemo1/subdemo1-sub1">按鈕1</Link> //但是這里就不一樣了,subdemo1-sub1層級是在subdemo1之下的,所以這里是 subdemo1/subdemo1-sub1
<Link to="/demo/subdemo1/subdemo1-sub2">按鈕2</Link>
<Route path="/demo/subdemo1"
render= { ()=>
<SubDemo1>
<Route path="/demo/subdemo1/subdemo1-sub1" component={SubDemo1Sub1} /> //還有這里,這里的path和Link方式是一樣的
<Route path="/demo/subdemo1/subdemo1-sub2" component={SubDemo1Sub2} />
</SubDemo1>
}
/>
PS:對,沒錯,就是這樣,就算在同一目錄下,如果層級不同,path,Link路徑引入還是要按照文件層級上下級來執行的,當然import的路徑就不是這樣了
默認路由
src
|__demo //demo1-sub1.js是demo1-index.js的子頁面,雖然在同一個文件夾下,但是路徑卻是上下級關系
|__demo1
| |__demo1-index.js
| |__demo1-sub1.js
| |__demo1-sub2.js
|__setting.js
|__demo2
|__demo2-index.js
|__demo2-sub1.js
|__demo2-sub2.js
<Switch>
<Route path={`/demo/setting`} exact component={ Setting } />
<Route path="/demo/demo1/demo1-index/demo1-sub1" component={Demo1Sub1} />
<Route path="/demo/demo2/demo2-index"
render={()=>
<Demo2Index>
<Switch> //——默認路由第 1 點,Switch語句——
<Route path="/demo/demo2/demo2-index" exact component={Demo2Sub1} /> //——默認路由第 2 點,默認路由給個exact={true}精准查找,path引入的是父頁面路徑,component是子頁面組件——
<Route path="/demo/demo2/demo2-index/demo2-sub2" component={Demo2Sub2} />
<Redirect path="/demo/demo2/demo2-index" to={{pathname:"/demo/demo2/demo2-index/demo2-sub2"}} /> //——默認路由第 3 點,使用Redirect,path引入的是父頁面路徑,to引入的是子頁面路徑(注意是指路由里的路徑,而不是文件里的路徑,如果算文件里的路徑則是/demo/demo2/demo2-sub2,這樣是不正確的)——
</Switch>
</Demo2Index>
}
/>
<Redirect to="/demo/setting" />
</Switch>
一個完整的默認進入登錄頁面的router.js(以前的懶得看了,就看這個吧,更直觀一些)
文件目錄
src
|__api
|__image
|__pages
|__login
|__commodity
|__user
|__allview
|__index.js
|__index.less
|__App.js
|__router.js
|__index.js
|__index.less
=== src/App.js頁面 ===
import React, { Component } from 'react';
export default class App extends Component {
render() {
return (
<div>
{this.props.children} //最頂級路由,用來存放同等級的幾個頁面如:登錄,注冊,用戶中心
</div>
);
}
}
=== src/index.js頁面 ===
import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';
- import App from './App';
+ import IRouter from './router';
import * as serviceWorker from './serviceWorker';
- ReactDOM.render(<App />, document.getElementById('root'));
+ ReactDOM.render(<IRouter />, document.getElementById('root'));
serviceWorker.unregister();
=== src/router.js頁面 ===
import React from 'react';
import {BrowserRouter,Route,Switch,Redirect} from 'react-router-dom';
import App from './App' //注意react腳手架里面,這個App是大寫開頭的
//登錄注冊部分
import Login from './pages/login/login' //登錄
import Register from './pages/login/register' //注冊
//用戶中心
import UserCenterIndex from './pages/index' //主頁面
//首頁部分
import Overview from './pages/allview/overview' //概覽
//用戶部分
import userInfo from './pages/user/userInfo' //用戶-用戶信息
import userStatis from './pages/user/userStatis' //用戶-用戶統計
//商品部分
import CommodityList from './pages/commodity/commodityList' //商品-商品列表
import CommodityPrice from './pages/commodity/commodityPrice' //商品-商品價格
export default class IRouter extends React.Component{
render(){
return(
<BrowserRouter>
<App> //最頂級路由,下面包裹所有子路由
<Switch>
{/* 登錄注冊 */}
<Route path="/pages/login/login" exact component={Login} /> //登錄,注冊,用戶中心這幾個路由都是平級的
<Route path="/pages/login/register" component={Register} />
<Route path="/pages" render={()=> //這一行要注意,解析在下面①
<UserCenterIndex> {/* 用戶中心 */}
<Switch>
{/* 概覽部分 */}
<Route path="/pages/allview/overview" component={Overview} />
{/* 用戶部分 */}
<Route path="/pages/user/userInfo" component={userInfo} />
<Route path="/pages/user/userStatis" component={userStatis} />
{/* 商品部分 */}
<Route path="/pages/commodity/commodityList" component={CommodityList} />
<Route path="/pages/commodity/commodityPrice" component={CommodityPrice} />
</Switch>
</UserCenterIndex>
} />
<Redirect to="/pages/login/login" /> //這句代碼的作用是,將localhost://3000/pages/login/login設置為默認路由 ②Redirect用法
</Switch>
</App>
</BrowserRouter>
);
}
}
① 這里需要講解一下,"/"相當於最高級路由,如果這里是path="/"而不是path="/pages",那么路由會首先跳轉到"/"。
且如果使用了switch,那么路由在跳轉到此路由之后便不再向下跳轉。
這樣的結果便是,路由開啟后,會默認跳轉到用戶中心(path="/")而不是登錄頁面(path="/pages/login/login")。
因為登錄頁面的path="/pages......",優先級是低於path="/"的,這里給定了switch,所以路由在跳轉到"/"后便不會再往下查找了。
所以,在命名路由路徑時,應盡量讓它們的根路徑相同。我之前的命名是:
概覽部分:path="/allview/overview"
用戶部分:path="/user/userInfo" path="/user/userStatis"
商品部分:path="/commodity/commodityList" path="/commodity/commodityPrice"
你看,我這樣命名,它們的根路徑就完全不相同,那我路由也不好做處理。只能設置path="/"來作為它們的根路由。因為"/"是它們唯一的共同根路由。
但是我這樣設置以后,頁面就默認跳轉不到登錄頁面(因為登錄頁面的根路由是"/pages/....."),而是用戶中心,這樣就與我的意向背道而馳。
所以我做了以下改動,我將它們的路由命名改為
概覽部分:path="/pages/allview/overview"
用戶部分:path="/pages/user/userInfo" path="/pages/user/userStatis"
商品部分:path="/pages/commodity/commodityList" path="/pages/commodity/commodityPrice"
這樣,我就能將用戶中心的根路由設置為path="/pages",與登錄頁面的根路由一樣。這樣,我就可以用Redirect將登錄頁面設置為默認路由了。
以上,是可以變通的,不過如果按照我的文件目錄搭建習慣來,就這樣寫就可以了。我的文件目錄搭建習慣看我react的另一篇博客:搭建一個react項目
② 之前有介紹過Redirect設置默認路由用法,那里即需要設置path,有需要to,<Redirect path="" to={{}} />。這里好像<Redirect to="" />就可以了。
在每個模塊里創建新的路由分支頁面來存放此模塊的路由,而不是所有路由都放在一個router.js里,這樣不易於管理,router.js里存放每個模塊的路由分支頁面就可以了
router.js頁面
import React from 'react';
import {BrowserRouter,Route,Switch,Redirect} from 'react-router-dom';
import App from './App'
import CommodityRouter from './pages/commodity/commodityRouter' //商品部分的路由分支頁面
export default class IRouter extends React.Component{
render(){
return(
<BrowserRouter>
<App>
<Switch>
<Route path="/pages/login/login" exact component={Login} />
<Route path="/pages/login/register" component={Register} />
<Route path="/pages" render={()=>
<UserCenterIndex> // ⑤⑤,userCenterIndex為父級頁面,包裹子級頁面
<Switch>
{/* 概覽部分 */}
<Route path="/pages/allview/overview" component={Overview} />
{/* 商品部分 */}
<Route path="/pages/commodity" component={CommodityRouter} /> //商品模塊路由分支,此處path應與⑩處一致(即此模塊的首頁面)
</Switch>
</UserCenterIndex>
} />
<Redirect to="/pages/login/login" />
</Switch>
</App>
</BrowserRouter>
);
}
}
commodityRouter.js頁面
import React from 'react';
import {Route,Switch,Redirect} from 'react-router-dom';
import CommodityIndex from './commodityIndex' //商品-商品主頁
import CommodityList from './commodityList' //商品-商品列表
export default class CommodityRouter extends React.Component{
render(){
return(
<div>
<main> //強調一下,main為h5新添加,IE瀏覽器不支持,若項目需兼容IE,則去除main
<Switch>
<Route path="/pages/commodity" exact component={CommodityIndex} /> // ⑩
<Route path="/pages/commodity/commodityList" component={CommodityList} />
<Redirect to="/pages/commodity" />
</Switch>
</main>
</div>
);
}
}
===== 最新版本 =====
目錄

===== src/index.js頁面 =====
import React from 'react';
import ReactDOM from 'react-dom';
import './index.less';
- import App from './App';
+ import IRouter from './router';
import * as serviceWorker from './serviceWorker';
- ReactDOM.render(<App />, document.getElementById('root'));
+ ReactDOM.render(<IRouter />, document.getElementById('root'));
serviceWorker.unregister();
===== src/App.js頁面 =====
import React from 'react';
export default class App extends React.Component{
render(){
return(
<div>{this.props.children}</div>
);
}
}
===== src/router.js主路由頁面 =====
import React from 'react'
import {BrowserRouter,Route,Switch,Redirect} from 'react-router-dom'
import App from './App'
import UserRouter from './pages/user/userRouter' //用戶中心界面路由
import HomeRouter from './pages/home/homeRouter' //展示頁路由
export default class IRouter extends React.Component{
render(){
return(
<BrowserRouter>
<App>
- <Switch> //方式一,路由樣式 http://localhost:3000/pages/user
- <Route path="/pages" //若要將路由定位到/pages/之后,可以使用此方式,即<Route path="/XXXX" render={()=><Switch>...</Switch>} />
- render={()=>
- <Switch> //若想要將下方路由設置為某一頁面的子路由,則使用父級路由包裹即可(見上方 ⑤⑤ 處)
- <Route path="/pages/user" component={UserRouter} />
- <Route path="/pages/home" component={HomeRouter} />
- <Redirect to="/pages/user" />
- </Switch>
- } />
- <Redirect to="/pages" /> //這里也需要重定向到 /XXXX
- </Switch>
+ <Switch> //方式二,路由樣式 http://localhost:3000/user
+ <Route path="/user" component={UserRouter} /> //這里的path需要與路由分支里的主路由一致,如下方的主路由若是/user(見下方 ①⑥ 處),則這里也必須設為/user
+ <Route path="/home" component={HomeRouter} />
+ <Redirect to="/user" />
+ </Switch>
</App>
</BrowserRouter>
);
}
}
===== src/pages/user/userRouter.js路由分支頁面 =====
import React from 'react';
import {Route,Switch,Redirect} from 'react-router-dom';
import Login from './login'
import Register from './register'
export default class UserRouter extends React.Component{
render(){
return(
<div>
<Switch>
<Route path="/user" exact component={Login} /> // ①⑥ , 這是此路由分支里的默認路由,/user
<Route path="/user/register" component={Register} /> //這是此路由分支里的一般路由,/user/register,注意區別,一般路由相當於默認路由的子路由,要在其后(如這里的/user之后)添加。如/user/register
<Redirect to="/user" />
</Switch>
</div>
)
}
}
===== src/pages/user/homeRouter.js路由分支頁面 =====
import React from 'react';
import {Route,Switch,Redirect} from 'react-router-dom';
import Home from './home'
import HomeShow from './homeShow'
export default class HomeRouter extends React.Component{
render(){
return(
<div>
<Switch>
<Route path="/home" exact component={Home} />
<Route path="/home/homeshow" component={HomeShow} />
<Redirect to="/home" />
</Switch>
</div>
)
}
}