index.tsx
import React from 'react'; import { BrowserRouter, HashRouter, Route, Link, NavLink, Switch, Redirect, } from 'react-router-dom'; import Header from './Comps/Header'; import MyNavLink from './Comps/MyNavLink'; import './index.css'; import About from './About'; import Home from './Home'; import News from './News'; const RouterDome: React.FC = () => { /* * react-router-dom 的使用,当前版本 5.3.0 * * BrowserRouter 历史模式路由, HashRouter hash模式路由 * 使用时 Route 时必须要用 BrowserRouter 或 HashRouter 包裹,而且只能有一个,可以直接包裹在App上。 * * NavLink 和 Link 的区别 * NavLink 可以设置 activeClassName 属性,当该属性与当前路径匹配时,会自动将属性内的类名添加到元素上 * <NavLink activeClassName="active" className="route-li" to="/about"> * * Switch 的 作用 * 可以提高路由匹配的效率 * 当多个 Route 存在相同的 path 时,那么这几个组件将会同时显示 * 如下:(Home 组件 和 About 组件 将同时显示) * <Route path="/home" component={Home}></Route> * <Route path="/home" component={About}></Route> * 若 使用 Switch 将 Route 包裹,那么当路由匹配当第一个组件时,将不再往下配置,则只会显示 Home 组件 * * router 的 模糊匹配(默认模式)和 严格匹配 * * 模糊匹配(匹配顺序是从左往右进行的) * 例子1 (匹配成功) * <NavLink to="/home/a/b/c">News</NavLink> * <Route path="/home" component={Home}></Route> * * 例子2 (匹配失败) * <NavLink to="/a/home/c">News</NavLink> * <Route path="/home" component={Home}></Route> * * 严格模式 * 开启严格匹配模式,在 Route 组件内 添加 exact 即可, 且 to 和 path 必须相同才能匹配成功 * 如: * <NavLink to="/about">News</NavLink> * <Route exact path="/about" component={About}></Route> * 需注意一般情况下,不要开启严格匹配模式,可能会导致二级路由匹配失败 * * Redirect 路由重定向 * 用法 <Redirect to="/home"></Redirect>,在 to 中指定需要展示的组件 * 当所有点路由都匹配不上时,该组件才会生效 * * 嵌套路由 * 子级路由必须以父级路由名称为开头,而且父级路由不能开启 exact 模式 * 如: * 父级 * <Route path="/news" component={News}></Route> * 子级 * <Route path="/news/compA" component={CompA}></Route> * <Route path="/news/compB" component={CompB}></Route> * * router params 参数 * 传参:<NavLink to="/news/compA/a">compA</NavLink> * 接收:<Route path="/news/compA/:type" component={CompA}></Route> * 获取参数:通过 props.match.params 即可拿到 type = a * * router search 参数 * 传参:<NavLink to="/news/compB?name=compB&type=B">compB</NavLink>;参数通过 ? 拼接在路径上,多个参数用 & 隔开,且无需去接收 * 获取参数:通过 props.location.search 获取,需注意这里获取到的参数是字符串 ?name=compB&type=B * 示例: * import React from 'react'; * import qs from 'querystring'; // 无需安装,此为自带的库 * * interface ICompB { * [propName: string]: any; * } * const CompB: React.FC<ICompB> = (props) => { * const { search } = props.location; * const query = qs.parse(search.slice(1)); * console.log(query); // { name: 'compB', type: 'B' } * return <h3>this is CompB</h3>; * }; * export default CompB; * * router state 参数 * 注意:HashRouter 模式下,刷新会导致 state 数据丢失,因此 HashRouter 模式下不推荐使用该方法传参 * 示例: * 传参:<NavLink to={{ pathname: '/news/compC', state: { name: 'compC', type: 'C' } }}>compC</NavLink> * 获取参数: * import React from 'react'; * const CompC: React.FC = (props) => { * console.log((props as any).location.state); // {name: 'compC', type: 'C'} * return <h3>this is CompC</h3>; * }; * export default CompC; * * router push 和 replace * push(默认模式),会在浏览器上留下记录 * replace 则是替换当前路径,且不会在浏览器留下记录 * 开启replace模式: * 如:<NavLink replace to="/news/compA/a">compA</NavLink>,<Link replace></Link> * * 编程式路由的使用 * 先熟悉下 props.history 几个常用的属性 * history: { * go: ƒ go(n), * goBack: ƒ goBack(), * goForward: ƒ goForward(), * push: ƒ push(path, state), * replace: ƒ replace(path, state) * } * go 的使用 * n 为正数则往后退,负数则往前退 * 示例:(props as any).history.go(n); * * goBack 的使用 * 往前退一步 * 示例:(props as any).history.goBack(); * * goForward 的使用 * 往后退一步 * 示例:(props as any).history.goForward(); * * push 的使用 * 第一种情况,params 参数 * 示例:(props as any).history.push('/news/compA/a'); * 第二种情况,search 参数 * 示例:(props as any).history.push('/news/compB?name=compB&type=B'); * 第三种情况,state 参数 * 示例:(props as any).history.push('/news/compC', { name: 'compC', type: 'C' }); * * replace 和 push 使用基本相同,只不过是 把 push 替换成了 replace,参考上面案例。 * 需注意以上的路由方法只能在路由组件中使用 * * withRouter * 作用:使一般组件也能像路由组件一样,调用 history 身上的方法 */ return ( <BrowserRouter> <div className="router-demo"> {/* 一般组件 */} <Header></Header> <div className="router-main"> <div className="left"> <ul> {/* <Link to="./home" className="route-li">Home</Link> */} <li> <NavLink activeClassName="active active2" className="route-li" to="/home"> Home </NavLink> </li> <li> <NavLink activeClassName="active" className="route-li" to="/about"> About </NavLink> </li> <li> <MyNavLink to="/news">News</MyNavLink> </li> </ul> </div> <div className="right"> <Switch> {/* <Route path="/home" component={Home}></Route> */} <Route path="/home" component={Home}></Route> <Route path="/about" component={About}></Route> <Route path="/news" component={News}></Route> <Redirect to="/home"></Redirect> </Switch> </div> </div> </div> </BrowserRouter> ); }; export default RouterDome;
News 组件
import React from 'react';
import { NavLink, Switch, Route, Redirect } from 'react-router-dom';
import CompA from './CompA';
import CompB from './CompB';
import CompC from './CompC';
import './index.css';
const News: React.FC = (props) => {
function onGo(n: number) {
// n 为正数则往后退,负数则往前退
(props as any).history.go(n);
}
function goBack() {
// 往前退一步
(props as any).history.goBack();
}
function goForward() {
// 往后退一步
(props as any).history.goForward();
}
function onPushParams() {
(props as any).history.push('/news/compA/a');
}
function onPushSearch() {
(props as any).history.push('/news/compB?name=compB&type=B');
}
function onPushState() {
(props as any).history.push('/news/compC', { name: 'compC', type: 'C' });
}
return (
<div className="news-content">
<h2>this is News</h2>
<button onClick={() => onGo(-1)}>go -1</button>
<button onClick={() => onGo(1)}>go 1</button>
<button onClick={() => goBack()}>goBack 往前退一步</button>
<button onClick={() => goForward()}>goForward 往后退一步</button>
<button onClick={() => onPushParams()}>push params 传参</button>
<button onClick={() => onPushSearch()}>push search 传参</button>
<button onClick={() => onPushState()}>push state 传参</button>
<ul>
<li>
<NavLink to="/news/compA/a">compA</NavLink>
</li>
<li>
<NavLink to="/news/compB?name=compB&type=B">compB</NavLink>
</li>
<li>
<NavLink to={{ pathname: '/news/compC', state: { name: 'compC', type: 'C' } }}>
compC
</NavLink>
</li>
</ul>
<Switch>
<Route path="/news/compA/:type" component={CompA}></Route>
<Route path="/news/compB" component={CompB}></Route>
<Route path="/news/compC" component={CompC}></Route>
<Redirect to="/news/compA/a"></Redirect>
</Switch>
</div>
);
};
export default News;
Header 组件
import React from 'react';
import { withRouter } from 'react-router-dom';
const Header: React.FC = (props) => {
function onGo(n: number) {
// n 为正数则往后退,负数则往前退
(props as any).history.go(n);
}
return (
<>
<h2>React Router Dome</h2>
<button onClick={() => onGo(-1)}>go -1</button>
<button onClick={() => onGo(1)}>go 1</button>
</>
);
};
export default withRouter(Header);