1. 什么是路由?
- 路由维护了URL地址和组件的映射关系, 通过这个映射关系, 我们就可以根据不同的URL地址,去渲染不同的组件
2.如何在React中使用路由 - 安装
react-router
npm install react-router-dom
- 通过指定监听模式
- BrowserRouter history模式 http://www.it666.com/home
- HashRouter hash模式 http://www.it666.com/#/home
- 通过Link修改路由URL地址
- 通过Route匹配路由地址
官网文档地址: https://reactrouter.com/web/guides/quick-start
2..BrowserRouter和HashRouter作用:
指定路由的监听模式 history模式 / hash模式
http://www.baidu.com/home history模式
http://www.baidu.com/#/home hash模式
3.Link作用
用于修改URL的资源地址
4.Route作用: - 用于维护URL和组件的关系
- Route是一个占用组件, 将来它会根据匹配到的资源地址渲染对应的组件
需求: 界面上有两个按钮, 点击不同按钮显示不同组件
import React from 'react'; import Home from './components/Home' import About from './components/About' //导入需要使用的组件 import {BrowserRouter, HashRouter, Link, Route} from 'react-router-dom'; class App extends React.PureComponent{ constructor(props){ super(props); } render(){ return ( <div> <HashRouter> <Link to={'/home'}>Home</Link> <Link to={'/about'}>About</Link> <Route path={'/home'} component={Home}/> <Route path={'/about'} component={About}/> </HashRouter> </div> ) } } export default App;
2.React路由注意点
2.1 react-router-dom和react-router-native
- react-router4之前, 所有路由代码都是统一放到
react-router
中管理的 - react-router4开始, 拆分为了两个包
react-router-dom
和react-router-native
react-router-dom
在浏览器中使用路由react-router-native
在原生应用中使用路由
2.2 BrowserRouter和HashRouter
-BrowserRouter history
模式使用的是H5的特性, 所以兼容性会比HashRouter
hash
模式差一些
- 在企业开发中如果不需要兼容低级版本浏览器, 建议使用
BrowserRouter
,如果需要兼容低级版本浏览器, 那么只能使用HashRouter
- 论是
Link
还是Route
都只能放到BrowserRouter
和HashRouter
中才有效
class App extends React.PureComponent{ render(){ return ( <div> {/*设置监听模式*/} <BrowserRouter> {/*修改路由地址*/} <Link to={'/home'}>Home</Link> <Link to={'/about'}>About</Link> {/*维护URL和组件关系*/} <Route path={'/home'} component={Home}/> <Route path={'/about'} component={About}/> </BrowserRouter> </div> ) } } export default App;
2.3 Route注意点
- 默认情况下
Route
在匹配资源地址时, 是模糊匹配 - 如果必须和资源地址一模一样才匹配, 那么需要添加
exact
属性, 开启精准匹配
2.4 Link注意点
- 默认情况下
Link
会渲染成一个a
标签, 如果想渲染成其他的元素, 可以通过手动路由跳转来实现
2.5.NavLink注意点
- 默认情况下
NavLink
在匹配资源地址时, 是模糊匹配,如果必须和资源地址一模一样才匹配, 那么需要添加exact
属性, 开启精准匹配
模糊匹配
NavLink在匹配路由的时候, 是利用当前资源地址从左至右的和path中的地址进行匹配的
只要当前资源地址从左至右完整的包含了path中的地址那么就认为匹配
当前资源地址 : /home/about
to中的地址: /home
to中的地址: /home/about
NavLink
在匹配路由的时候, 是利用当前资源地址从左至右的和path
中的地址进行匹配的,只要当前资源地址从左至右完整的包含了path
中的地址那么就认为匹配NavLink
有一个Link
没有的属性activeStyle
<NavLink exact to={'/home'} activeStyle={{color:'red'}}>Home</NavLink> <NavLink exact to={'/home/about'} activeStyle={{color:'red'}}>About</NavLink> //当前资源地址 : /home/about,to中的地址: /home&& /home/about,因为是模糊匹配
3. Switch
默认情况下路由会从上至下匹配所有的Route, 只要匹配都会显示,但是在企业开发中大部分情况下, 我们希望的是一旦有一个匹配到了后续就不要再匹配了
此时我们就可以通过Switch来实现
import React from 'react'; import Home from './components/Home' import About from './components/About' import Other from './components/Other' import {BrowserRouter, Link, Route, Switch} from 'react-router-dom'; class App extends React.PureComponent{ render(){ return ( <div> <BrowserRouter> <Link to={'/home'}>Home</Link> <Link to={'/about'}>About</Link> <Switch> <Route exact path={'/home'} component={Home}/> <Route exact path={'/about'} component={About}/> {/*如果Route没有指定path, 那么表示这个Route和所有的资源地址都匹配*/} <Route component={Other}/> </Switch> </BrowserRouter> </div> ) } } export default App;
image.png
Redirect
Redirect:资源重定向, 也就是可以在访问某个资源地址的时候重定向到另外一个资源地址
例如: 访问/user 重定向到 /login
注意点:如果要使用嵌套路由, 那么外层路由不能添加精准匹配exact
import React from 'react'; import {Redirect} from 'react-router-dom'; class User extends React.PureComponent{ constructor(props){ super(props); this.state = { isLogin: false } } render(){ let user = ( <div> <h1>用户界面</h1> <p>用户名: yiya_xiaoshan</p> <p>密码: www.baidu.com</p> </div> ); let login = <Redirect to={'/login'}/> return this.state.isLogin ? user : login; } } export default User;
嵌套路由
路由里面又有路由, 就称之为嵌套路由
//app.js import React from 'react'; import Home from './components/Home' import About from './components/About' import Other from './components/Other' import User from './components/User' import Login from './components/Login' import Discover from './components/Discover' import {BrowserRouter, NavLink, Route, Switch} from 'react-router-dom'; class App extends React.PureComponent{ render(){ return ( <div> <BrowserRouter> <NavLink to={'/home'} activeStyle={{color:'red'}}>Home</NavLink> <NavLink to={'/about'} activeStyle={{color:'red'}}>About</NavLink> <NavLink to={'/user'} activeStyle={{color:'red'}}>User</NavLink> <NavLink to={'/discover'} activeStyle={{color:'red'}}>广场</NavLink> <Switch> <Route exact path={'/home'} component={Home}/> <Route exact path={'/about'} component={About}/> <Route exact path={'/user'} component={User}/> <Route exact path={'/login'} component={Login}/> <Route path={'/discover'} component={Discover}/> <Route component={Other}/> </Switch> </BrowserRouter> </div> ) } } export default App;
//discover界面 import React from 'react'; import {NavLink, Switch, Route} from "react-router-dom"; function Hot() { return ( <div>推荐</div> ) } function TopList() { return ( <div>排行榜</div> ) } function PlayList() { return ( <div>歌单</div> ) } class Discover extends React.PureComponent{ render(){ return ( /* 注意点: 由于当前组件是在BrowserRouter or HashRouter中显示的 所以在当前组件中不用使用BrowserRouter or HashRouter来包裹NavLink/Switch/Route * */ <div> <NavLink exact to={'/discover'} activeStyle={{color:'red'}}>推荐</NavLink> <NavLink exact to={'/discover/toplist'} activeStyle={{color:'red'}}>排行榜</NavLink> <NavLink exact to={'/discover/playlist'} activeStyle={{color:'red'}}>歌单</NavLink> <Switch> <Route exact path={'/discover'} component={Hot}/> <Route exact path={'/discover/toplist'} component={TopList}/> <Route exact path={'/discover/playlist'} component={PlayList}/> </Switch> </div> ) } } export default Discover;
通过JavaScript手动路由
1.手动路由跳转:
不通过Link/NavLink
来设置资源地址, 而是通过JS来设置资源地址
- Hash模式
如果是Hash模式, 那么只需要通过JS设置Hash值即可window.location.hash = '/discover/playlist';
如果一个组件是通过路由创建出来的, 那么系统就会自动传递一个history给我们 - history模式
我们只需要拿到这个history
对象, 调用这个对象的push
方法, 通过push
方法修改资源地址即可
console.log(this.props.history);
btnClick(){ //hash模式 window.location.hash = '/discover/playlist'; // history 模式 console.log(this.props.history); this.props.history.push('/discover/playlist'); }
1.手动路由跳转注意点:
- 只有通过路由创建出来的组件才有
history
对象, 所以不能在根组件中使用手动路由跳转 - 如果想在根组件中使用手动路由跳转, 那么需要借助一个
withRouter
高阶组件 - 如果一个组件是通过路由创建的, 那么系统就会自动给这个组件传递一个
history
对象
但是如果一个组件不是通过路由创建的, 那么系统就不会给这个组件传递一个history
对象 - 如果现在非路由创建出来的组件中使用
history
对象, 那么可以借助withRouter
高阶组件 - 只要把一个组件传递给
withRouter
方法, 那么这个方法就会通过路由将传入的组件创建出来 - 注意点: 如果一个组件要使用路由创建, 那么这个组件必须包裹在
BrowserRouter, HashRouter
中
import React from 'react'; import Home from './components/Home' import About from './components/About' import Other from './components/Other' import User from './components/User' import Login from './components/Login' import Discover from './components/Discover' import {BrowserRouter, HashRouter, NavLink, Route, Switch, withRouter} from 'react-router-dom'; class App extends React.PureComponent{ render(){ return ( <div> <NavLink to={'/home'} activeStyle={{color:'red'}}>Home</NavLink> <NavLink to={'/about'} activeStyle={{color:'red'}}>About</NavLink> <NavLink to={'/user'} activeStyle={{color:'red'}}>User</NavLink> <NavLink to={'/discover'} activeStyle={{color:'red'}}>广场</NavLink> <button onClick={()=>{this.btnClick()}}>广场</button> <Switch> <Route exact path={'/home'} component={Home}/> <Route exact path={'/about'} component={About}/> <Route exact path={'/user'} component={User}/> <Route exact path={'/login'} component={Login}/> <Route path={'/discover'} component={Discover}/> <Route component={Other}/> </Switch> </div> ) } btnClick(){ // window.location.hash = '/discover'; //Cannot read property 'push' of undefined this.props.history.push('/discover'); } } export default withRouter(App);
5.路由参数传递
1.路由参数传递
- URL参数
?key=value&key=value
- 路由参数(动态路由)
/path/:key
- 对象
https://reactrouter.com/web/api/Link