在web下我们一般都使用react-router-dom,相比于react-router多了一些DOM操作方法,你可以尝试单独安装react-router-dom,看依赖包里面是不是会包含了react-router,本文就记录下react-router-dom一些笔记(文章中api示例只给出了常用,详细api请查看官方文档)长篇文章警告!
安装
npm install react-router-dom
基本使用
import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
const Router = () => {
return (
<BrowserRouter>
<Switch>
<Route path='/' exact component={AsyncHome}/>
<Route path='/hot' exact component={AsyncHot}/>
</Switch>
</BrowserRouter>
)
}
export default Router
// 然后在App.js
import Router from './router';
const App = () => {
render(){
return (
<React.Fragment>
<Header/>
{router}
</React.Fragment>
)
}
}
export default App
//最后在inde中引用App即可
基本组件
React-Router
中有三种类型的组件:路由器组件,路由匹配组件和导航组件
路由器组件
react-router-dom
提供<BrowserRouter>
和<HashRouter>
路由器
<BrowserRouter>
:原理是使用HTML5 history API,内容随着url动态改变<HashRouter>
:有是根据hash值对路由进行控制的(会有#)
举个例子:
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
路由匹配组件
有两个路由匹配组件:<Route>
和<Switch>
-
<Route>
:Route是路由的一个原材料,它是控制路径对应显示的组件。经常用的是exact、path以及component属性
exact:控制匹配到/路径时不会再继续向下匹
path:路由的路径
component:显示组件 -
<Switch>
:Switch常常会用来包裹Route,它里面不能放其他元素,用来只显示一个路由。
举个例子:
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />
</Switch>
API:
名称 | 示例 | 属性 | 作用 |
---|---|---|---|
path | /users/:id | string | 定义路径 |
exact | exact path="/one" | bool | 严格匹配 |
导航组件
<Link>
和<NavLink>
一般在组件内跳转链接用的
<Link>
:<Link to="/home">
to可以接收一个string和object<NavLink>
:可以为当前选中的路由设置类名、样式以及回调函数等
举个例子:
<Link
to={{
pathname: "/courses",
search: "?sort=name",
hash: "#the-hash",
state: { fromDashboard: true }
}}
/>
<NavLink
to="/faq"
activeStyle={{
fontWeight: "bold",
color: "red"
}}
>
FAQs
</NavLink>
API:
<Link>
名称 | 示例 | 属性 | 作用 |
---|---|---|---|
to | to="/home" | string | 跳转路径 |
exact | exact to="/one" | bool | 严格匹配 |
<NavLink>
名称 | 示例 | 属性 | 作用 |
---|---|---|---|
to | to="/home" | string/object | 跳转路径 |
exact | exact to="/one" | bool | 严格匹配 |
activeClassName | activeClassName=‘active’ | string | 当前路径选中状态的类名 |
代码拆分
其实就是按需加载,不管是官方还是开发者,都有给出自己的方式,这里给出官方的示例代码,在我看来还是挺简单的!
create-react-app
npm install @babel/plugin-syntax-dynamic-import
//router>index.js
import Loadable from "react-loadable";
import Loading from "./Loading";
const Home = Loadable({
loader: () => import("./home"),
loading: Loading//必须配置loading组件,不然报错
});
const Router = () => {
return (
<BrowserRouter>
<Switch>
<Route path='/' exact component={Home}/>
</Switch>
</BrowserRouter>
)
}
export default Router
更多按需加载的方法请参考:https://segmentfault.com/a/1190000009539836
重定向
使用<Redirect>
可以重定向路径
import { Route, Redirect } from 'react-router'
//to是string的时候
<Route exact path="/" render={() => (
loggedIn ? (
<Redirect to="/dashboard"/>
) : (
<PublicHomePage/>
)
)}/>
//进入首页,判断是否已登陆,如果登陆重定向到用户面板
//当to是object的时候
<Redirect
to={{
pathname: "/login",
search: "?utm=your+face",
state: { referrer: currentLocation }
}}
/>
match
match是在使用router之后被放入props中的一个属性(/home/:id)
match对象包含以下属性:
- params - (对象)从与路径的动态段对应的URL解析的键/值对
- isExact- (boolean)是否是严格模式
- path - (字符串)用于匹配的路径模式。
- url - (字符串)URL的匹配部分。
withRouter
使用过vue-router的同学可能刚开始会很奇怪,为什么react-router没有直接在组件中js跳转路由的方法,比如this.$router.push
withRouter:是一个可以让你访问history
对象的属性和最近<Route>
的match
的高阶组件
利用withRouter达到路由js跳转
import React from "react";
import {withRouter } from 'react-router-dom';
class TLogin extends React.Component {
handleJump(){//在方法内调用
this.props.history.push('/home')
}
render() {
//dosomething
}
}
const Login = withRouter(TLogin)
export default Login;
//使用react-redux的时候
onst Login = withRouter(connect(...)(TLogin))
export default Login;
路由嵌套
v4中不支持以前这种写法
<Route path="/" component={App}>
<Route path="about" component={About} />
<Route path="inbox" component={Inbox}>
<Route path="messages/:id" component={Message} />
</Route>
</Route>
v4中子路由,应写在对应的组件内部中,当然你可以用react-router-config
对象的方式配置嵌套,和vue-router一样的。
npm install --save react-router-config
//app.js
import {renderRoutes} from 'react-router-config';
import Router from './router';
const App = () => {
render(){
return (
<React.Fragment>
<Header/>
{renderRoutes(Router)}
</React.Fragment>
)
}
}
export default App
//./router
export const Router = [
{
component: home,
path:'/',
},{
component:parent,
path:'/parent',
routes: [
{
path: "/parent/:id",
component: Child,
routes: [
{
path: "/parent/:id/grand-child",
component: GrandChild
}
]
}
]
}
];
异步加载组件
1.新建AsyncComponents组件
import React, {Component} from 'react';
export default function asyncComponents(importComponent) {
class AsyncComponent extends Component {
constructor(props) {
super(props);
this.state = {
component: null,
}
}
async componentDidMount() {//异步
const {default: component} = await importComponent();
this.setState({
component: component
});
}
render() {
const C = this.state.component;
return C ? <C {...this.props} /> : null;
}
}
return AsyncComponent
}
2、在router>index.js
import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import asyncComponents from "../components/AsyncComponents"
const AsyncHome = asyncComponents(() => import('../page/home/home'));
const AsyncHot = asyncComponents(() => import('../page/hot/hot'));
const router = (
<BrowserRouter>
<Switch>
<Route path='/' exact component={AsyncHome}/>
<Route path='/hot' exact component={AsyncHot}/>
</Switch>
</BrowserRouter>
);
export default router