1引入react-router-dom包
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的路径就不是这样了
带不带js后缀?
Link,path好像是不需要带js后缀的,path="./demo/demo1.js" path="./demo/demo1"今天项目中遇到了这个问题,只知道这次的是不能带的。但是之前自己写的一个react项目,好像不带又不行。
这可难住我胖虎了。总之先记上——————等不那么菜了,再回来看看这个问题。(可以带js也可以不带,不带的话在Link时就不要带,带的话,Link时也就带上。只要使用到路由的各个地方保持一致就行。但是不带的话,方便一些,路由嘛,没必要带js后缀。2019.6.24)
默认路由
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
=== app.js页面 ===
import React, { Component } from 'react';
export default class App extends Component {
render() {
return (
<div>
{this.props.children} //最顶级路由,用来存放同等级的几个页面如:登录,注册,用户中心
</div>
);
}
}
=== router.js页面 ===
import React from 'react';
import {BrowserRouter,Route,Switch,Redirect} from 'react-router-dom';
import App from './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>
<Switch>
{/* 概览部分 */}
<Route path="/pages/allview/overview" component={Overview} />
{/* 商品部分 */}
<Route path="/pages/commodity" component={CommodityRouter} /> //商品模块路由分支
</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>
<Switch>
<Route path="/pages/commodity" exact component={CommodityIndex} />
<Route path="/pages/commodity/commodityList" component={CommodityList} />
<Redirect to="/pages/commodity" />
</Switch>
</main>
</div>
);
}
}