一.react-router依赖
react-router依赖于react-router-dom
所以使用react-router必须先得安装react-router-dom
npm i react-router-dom
复制代码
二.react-router基本组件
-
BrowserRouter或HashRouter
- Router中包含了对路径改变的监听,并且会将相应的路径传递给子组件;
- BrowserRouter使用history模式;
- HashRouter使用hash模式;
-
Link和NavLink:
- 通常路径的跳转是使用Link组件,最终会被渲染成a元素;
- NavLink是在Link基础之上增加了一些样式属性(后续学习);
- to属性:Link中最重要的属性,用于设置跳转到的路径;
-
Route:
- Route用于路径的匹配;
- path属性:用于设置匹配到的路径;
- component属性:设置匹配到路径后,渲染的组件;
- exact:精准匹配,只有精准匹配到完全一致的路径,才会渲染对应的组件;
最基本的使用
import React, { PureComponent } from "react";
import { BrowserRouter, Route, NavLink, Switch } from "react-router-dom";
import About from "./About";
import Home from "./Home";
import Profile from "./Profile";
import "./App.css";
class App extends PureComponent {
render() {
return (
<BrowserRouter>
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Link to="/profile">我的</Link>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
</BrowserRouter>
);
}
}
export default App;
复制代码
NavLink的使用
路径选中时,对应的a元素变为红色
- activeStyle:活跃时(匹配时)的样式;
- activeClassName:活跃时添加的class;
- exact:是否精准匹配;
<NavLink to="/" activeStyle={{color: "red"}}>首页</NavLink>
<NavLink to="/about" activeStyle={{color: "red"}}>关于</NavLink>
<NavLink to="/profile" activeStyle={{color: "red"}}>我的</NavLink>
复制代码
使用NavLink组件时,被激活的路由也就是a标签上会多一个active类,这个类名可以自定义。
Switch的使用
- 提供路径与组件的唯一映射关系
- 只要匹配到了第一个,那么后面的就不应该继续匹配了;
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
<Route path="/:userid" component={User} />
<Route component={NoMatch} />
</Switch>
复制代码
Redirect的使用
Redirect用于路由的重定向,当这个组件出现时,就会执行跳转到对应的to路径中:
我们这里使用这个的一个案例:
-
用户跳转到User界面;
-
但是在User界面有一个isLogin用于记录用户是否登录:
- true:那么显示用户的名称;
- false:直接重定向到登录界面;
App.js中提前定义好Login页面对应的Route:
<Switch>
...其他Route
<Route path="/login" component={Login} />
<Route component={NoMatch} />
</Switch>
复制代码
在User.js中写上对应的逻辑代码:
import React, { PureComponent } from 'react'
import { Redirect } from 'react-router-dom';
export default class User extends PureComponent {
constructor(props) {
super(props);
this.state = {
isLogin: false
}
}
render() {
return this.state.isLogin ? (
<div>
<h2>User</h2>
<h2>用户名: coderwhy</h2>
</div>
): <Redirect to="/login"/>
}
}
复制代码
三.react-router高级
路由嵌套
在开发中,路由之间是存在嵌套关系的。
这里我们假设about页面中有两个页面内容:
- 商品列表和消息列表;
- 点击不同的链接可以跳转到不同的地方,显示不同的内容;
import React, { PureComponent } from 'react';
import { Route, Switch, Link } from 'react-router-dom';
function AboutProduct(props) {
return (
<ul>
<li>商品列表1</li>
<li>商品列表2</li>
<li>商品列表3</li>
</ul>
)
}
function AboutMessage(props) {
return (
<ul>
<li>消息列表1</li>
<li>消息列表2</li>
<li>消息列表3</li>
</ul>
)
}
export default class About extends PureComponent {
render() {
return (
<div>
<Link to="/about">商品</Link>
<Link to="/about/message">消息</Link>
<Switch>
<Route exact path="/about" component={AboutProduct} />
<Route path="/about/message" component={AboutMessage} />
</Switch>
</div>
)
}
}
复制代码
手动跳转
除了上述使用Link和NavLink跳转完,还可以使用JavaScript进行跳转。
前提是必须获取到history对象
获取方法
- 方式一:如果该组件是通过路由直接跳转过来的,那么可以直接获取history、location、match对象;
- 方式二:如果该组件是一个普通渲染的组件,将其用withRouter包裹,之后获取history、location、match对象;
传递参数
传递参数有三种方式:
- 动态路由的方式;
- search传递参数;
- to传入对象;
动态路由的方式
<div>
...其他Link
<NavLink to="/detail/abc123">详情</NavLink>
<Switch>
... 其他Route
<Route path="/detail/:id" component={Detail}/>
<Route component={NoMatch} />
</Switch>
</div>
复制代码
可以直接通过match对象中获取id;
search传递参数
<NavLink to="/detail2?name=why&age=18">详情2</NavLink>
<Switch>
<Route path="/detail2" component={Detail2}/>
</Switch>
复制代码
获取search
import React, { PureComponent } from 'react'
export default class Detail2 extends PureComponent {
render() {
console.log(this.props.location.search); // ?name=why&age=18
return (
<div>
<h2>Detail2:</h2>
</div>
)
}
}
复制代码
to传入对象
to可以直接传入一个对象
<NavLink to={{
pathname: "/detail2",
query: {name: "kobe", age: 30},
state: {height: 1.98, address: "洛杉矶"},
search: "?apikey=123"
}}>
详情2
</NavLink>
复制代码
获取参数:
import React, { PureComponent } from 'react'
export default class Detail2 extends PureComponent {
render() {
console.log(this.props.location);
return (
<div>
<h2>Detail2:</h2>
</div>
)
}
}
复制代码
四.react-router-config
目前我们所有的路由定义都是直接使用Route组件,并且添加属性来完成的。
但是这样的方式会让路由变得非常混乱,我们希望将所有的路由配置放到一个地方进行集中管理:
- 这个时候可以使用react-router-config来完成;
安装react-router-config:
npm install react-router-config
复制代码
常见router/index.js文件:
import Home from "../pages/home";
import About, { AboutMessage, AboutProduct } from "../pages/about";
import Profile from "../pages/profile";
import Login from "../pages/login";
import User from "../pages/user";
import Detail from "../pages/detail";
import Detail2 from "../pages/detail2";
import NoMatch from "../pages/nomatch";
const routes = [
{
path: "/",
exact: true,
component: Home
},
{
path: "/about",
component: About,
routes: [
{
path: "/about",
exact: true,
component: AboutProduct
},
{
path: "/about/message",
component: AboutMessage
},
]
},
{
path: "/profile",
component: Profile
},
{
path: "/login",
component: Login
},
{
path: "/user",
component: User
},
{
path: "/detail/:id",
component: Detail
},
{
path: "/detail2",
component: Detail2
},
{
component: NoMatch
}
];
export default routes;
复制代码
在需要调用该路由组的地方使用
{renderRoutes(routes)}
复制代码
如果是子组件中,需要路由跳转,那么需要在子组件中使用renderRoutes函数:
- 在跳转到的路由组件中会多一个
this.props.route
属性; - 该
route
属性代表当前跳转到的路由对象,可以通过该属性获取到routes
;
export default class About extends PureComponent {
render() {
return (
<div>
<Link to="/about">商品</Link>
<Link to="/about/message">消息</Link>
{renderRoutes(this.props.route.routes)}
</div>
)
}
}
复制代码
实际上react-router-config中还提供了一个matchRoutes
辅助函数:
matchRoutes(routes, pathname)
传入一个路由对象数组,获取所有匹配的路径;
const routes = matchRoutes(this.props.route.routes, "/about");
console.log(routes);
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END