- 创建项目 npx create-react-app react-router-demo
- 安装 cnpm i react-router-dom —save
**
import {BrowserRouter as Router, Switch, Route, Link} from 'react-router-dom'
// hash路由
import {HashRouter as Router, Switch, Route, Link} from 'react-router-dom'
function App() {
return (
<div className="App">
123
// 用Router 最外层包裹
<Router>
// 组件大写 路由小写
<Route path='/home' component={ Home }></Route>
<Route path='/mine' component={ Mine }></Route>
</Router>
</div>
);
}
- 组件分开归类
// import {BrowserRouter as Router, Switch, Route, Link} from 'react-router-dom'
import {HashRouter as Router, Route} from 'react-router-dom'
import Nav from './components/nav'
/**
* HashRouter 锚点链接
* BrowserRouter h5新特性 history.push(), 上线后需要后台做一些处理, 重定向处理,404bug
*/
function App() {
return (
<div className="App">
123
<Router>
<Nav />
<Route path='/home' component={ Home }></Route>
<Route path='/mine' component={ Mine }></Route>
</Router>
</div>
);
}
export default App;
---------------------------------
import React from 'react';
import {Link} from 'react-router-dom'
export default class Nav extends React.Component{
render() {
return (
<ul>
<li>
<Link to='/home'>首页</Link>
</li>
<li>
<Link to='/mine'>我的</Link>
</li>
</ul>
)
}
}
- 精确匹配 exact
// 路由包含字段就会显示, 要用精确匹配
<Route exact path='/mine' component={ Mine }></Route>
<Route path='/mine/ucenter' component={ UCenter }></Route>
- 精准匹配 strict 和 exact同时使用, /mine可以访问,/mine/ 不可以访问
<Route strict exact path='/mine/ucenter' component={ UCenter }></Route>
- Switch 只显示一个页面 , 包裹Route
function App() {
return (
<div className="App">
123
<Router>
<Nav />
<Switch>
<Route strict exact path='/' component={ Home }></Route>
<Route exact path='/mine' component={ Mine }></Route>
<Route strict exact path='/mine/ucenter' component={ UCenter }></Route>
<Route component={ NotFound }></Route>
</Switch>
</Router>
</div>
);
}
render渲染方式
<Route exact path='/demo' component={ () => <div>hello demo</div> }></Route>
// 引入 传参,不会在 url中显示参数
<Route exact path='/demo1' component={ (props) => <Demo {...props} name='你好'/> }></Route>
import React from 'react';
const Demo = (props) => {
console.log(props)
return (
<div>
demo {props.name}
</div>
)
}
// 或者 解构赋值
const Demo = ({name}) => {
return (
<div>
demo {props.name}
</div>
)
}
export default Demo
选中的路由高亮
-activeClassName 修改 激活的 类名
-activeStyle 双大括号, 行内 样式
-exact精确匹配
import React from 'react';
import {Link, NavLink} from 'react-router-dom'
import './style.css'
export default class Nav extends React.Component{
render() {
return (
<ul>
<li>
<NavLink exact className="NavLink" activeClassName="active" to='/'>首页</NavLink>
</li>
<li>
<NavLink exact className="NavLink" activeStyle={{color:'orange'}} to='/mine'>我的</NavLink>
</li>
<li>
<NavLink exact className="NavLink" to='/mine/ucenter'>center</NavLink>
</li>
</ul>
)
}
}
- 选中的样式
.NavLink.active {
color: red;
}
路由跳转 path 传参
- 参数后面 问号? 代表这个参数可有可无
```javascript
// 接收 const UCenter = (props) => { return (
你好center {props.match.params.id}
)
}
<a name="VpRBg"></a>
### url ? 传参
- [http://localhost:3000/#/mine?name=啦啦啦&sex=male](http://localhost:3000/#/mine?name=我那个&age=male)
两种获取参数的方式
```javascript
import React from 'react';
import querystring from 'querystring'
/**
* 正常是 先问号 再 hash
* 注意 ?参数 在 哈希中 还是正常的url中 localtion.search 会拿不到
*/
const Mine = (props) => {
// 第一种方式
// const params = new URLSearchParams(props.location.search)
// console.log(params.get('name'))
// 第二种方式
const value = querystring.parse(props.location.search.slice(1))
console.log(value)
return (
<div>
mineminemine
</div>
)
}
export default Mine
- 对象传值
<NavLink
to={{
pathname: '/mine',
search: '?sort=name',
hase: '#hash',
state: { flag: 'flag' } // 隐式传参,url不显示
}}
>我的</NavLink>
页面权限
- 怎么不用每个页面都引入 全局公共的 ? vue有 路由拦截, 一次就好 ```javascript import React from ‘react’; import {Redirect} from ‘react-router-dom’
const Shop = () => {
let isLogin = true
return (
{
isLogin ?
}
)
}
商品页面
:
<a name="Luz1U"></a>
#### 页面点击跳转 ,
- 函数型 直接可以使用props
```javascript
const Mine = (props) => {
/**
* push 铁架的上一次的页面依然存在内存中
* replace 是替换, 上一次的页面不存在了
*/
const routerHome = () => {
props.history.push('/')
}
return (
<div>
mineminemine
<button onClick={ routerHome }>回到Home</button>
</div>
)
}
- 类 需要使用 withRouter 包裹
import React from 'react';
import { withRouter } from 'react-router-dom'
class MineDemo extends React.Component {
handleBack = () => {
console.log(this.props) // 不用withRouter, 空对象
this.props.history.push('/')
}
// 当前组件没有直接被路由管理,所以没有对象
// withRouter
render() {
return (
<div>
<button onClick={ this.handleBack }>回到homedemo</button>
</div>
)
}
}
// 高阶组件
export default withRouter(MineDemo)
页面离开前判断 (Prompt)
import React from 'react';
import { Prompt } from 'react-router-dom'
export default class BeforeLeave extends React.Component {
state = {
val: ''
}
render() {
return (
<div>
<input type="text" value={ this.state.val } onChange={ (e) => {this.setState({val: e.target.value})}}/>
<Prompt
when={ !!this.state.val } //转为boolean 值, false 随便跳转, true 弹出提示
message={ '确认离开么' }
/>
</div>
)
}
}
路由嵌套
function App() {
return (
<div className="App">
123
<Router>
<Nav />
<Switch>
{/* <Route strict exact path='/book' component={ Book }></Route> */}
<Book>
<Switch>
<Route path='/book/web' component={ WebBook } />
<Route path='/book/java' component={ JavaBook } />
</Switch>
</Book>
<Route component={ NotFound }></Route>
</Switch>
</Router>
</div>
);
}
- book 组件中需要使用this.props.children 才能显示子路由
import React from 'react';
export default class Book extends React.Component {
render() {
return (
<div>
我是 book
{
this.props.children
}
</div>
)
}
}