学习react-router@5
前一篇react-router的文章写之前是参考网上的一些其他的文章的,理解的确实有许多问题,这次我阅读了react-router的官方文档,有了许多深层的理解,在这里记录一二。
本文基于react-router@5.3.2
前言
本文基于react-router@5.3.2,使用create-react-app脚手架
文章搭配的示例仓库链接
官方组件
Router
react-router的其他所有组件都必须放在BrowserRouter、HashRouter或MemoryRouter里。官方推荐使用BrowserRouter。
BrowserRouter使用浏览器的原生路径(path)作路由,使用( pushState,replaceState 和 popstate )使UI与URL保持同步。值得注意的是,这种路由必须配合后端使用,否则可能出现404的现象。
HashRouter使用URL的hash部分作路由,例如:https://xxx.xxx/#/abc就表示/abc,如果不能改后端,建议使用这种方法。
MemoryRouter把路由信息存在内存里,刷新就没有了,不推荐。
function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/text" component={}/>
</Switch>
</BrowserRouter>
)
}
Link
官方建议使用Link代替a组件作路由跳转。不需要了解太多,为了防止出现错误,照着使用即可。
function App() {
return (
<NavLink to="/test">测试</NavLink>
)
}
NavLink
这个组件和Link类似,但当它的path与路由匹配时,它会获得一个默认叫active的class,用于展示特殊的CSS样式
.link-active {
color: red;
}
import "default.css";
function App() {
return (
<NavLink activeClassName="link-active" to="/test">测试</NavLink>
)
}
Prompt
这个组件用于向用户确认是否切换路由或关闭页面,防止用户因误操作二导致很多输入的内容消失。比如填了很久的表单因为一个误操作就得重填什么的。用法如下:
function App() {
const [input, setInput] = useState();
return (
<BrowserRouter>
<input value={input} onChange={e => {setInput(e.target.value)}}/>
<Prompt when={!!input} message="输入不会自动保存,确认退出?"/>
</BrowserRouter>
)
}
Redirect
从意思因该就能看出来,就是重定向的意思,当react渲染该组件的时候,会立即重定向到指定路由,不会留下历史记录,常常和Switch搭配使用。
function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/" exact component={Home}/>
<Route path="/a" component={A}/>
<Route path="/b" component={B}/>
<Route path="404" component={NotFound}/>
<Redirect to="/404"/>
</Switch>
</BrowserRouter>
)
}
Route
一个路由,当设定的path满足路由时,渲染组件。它有一些值得注意的地方:
-
path匹配有点复杂,这里直接举例说明对于
<Route path="/asd"/>匹配:
/abc、/abcdefg、/abc/asdfgfgh/safd、/abc/不匹配:
/123、/加上exact精确匹配:
<Route exact path="/abc"/>匹配:
/abc,/abc/不匹配:
/abc、/abc/123、/123加上
strict:<Route exact path="/abc"/>只匹配:
/abc -
渲染子组件有三种方式:
-
component属性直接指定子组件,这样就不能传参数了
function App() { return ( <BrowserRouter> <Route path="/" exact component={Home}/> </BrowserRouter> ) } -
render属性指定函数返回元素,解决了传参问题
function App({handleClick}) { return ( <BrowserRouter> <Route path="/" exact render={() => <MyButton handleClick={handleClick}/>} /> </BrowserRouter> ) } -
children属性这个我也不懂,就贴一个官网的例子吧
const ListItemLink = ({ to, ...rest }) => ( <Route path={to} children={({ match }) => ( <li className={match ? 'active' : ''}> <Link to={to} {...rest}/> </li> )}/> )
警告:
<Route component>和<Route render>优先于<Route children>,因此不要在同一个<Route>中使用多个。 -
Switch
这个官网写的也有点难理解
简单来说,就是Switch下只能包含一个或多个Route组件,并且最多只会渲染从上到下第一个匹配成功的组件,听不懂?看例子吧
function App() {
return (
<BrowserRouter>
<Switch>
<Route path="/" exact component={Home}/>
<Route path="/a" component={A}/>
<Route path="/asd" component={ASD}/>
<Route path="404" component={NotFound}/>
<Redirect to="/404"/>
</Switch>
</BrowserRouter>
)
}
上面这个例子,
| URL | 渲染的组件 |
|---|---|
/ |
Home |
/a |
A |
/asd |
A(注意不是ASD) |
/bbb |
NotFound(重定向) |
withRouter
一个函数,输入组件,返回一个组件的封装,只是props加上了history
注意:在使用react时,不能直接从全局变量中获取
history对象,而是需要使用withRouter封装组件,从组件的参数中获取。具体请看例子。
function App({history}) {
const [path, setPath] = useState("/this-path/");
return (
<div>
<input type="text" value={path} onChange={(event) => {
const v = event.target.value;
if (v.search(/^\/this-path\//) === 0) {
setPath(v);
} else {
setPath("/this-path/")
}
}}/>
<button onClick={() => {history.push(path)}}>跳转</button>
<Route path="/this-path/:p" component={ShowParams}/>
</div>
)
}
// 顺便把传参也写在这里了
function ShowParams({match}) {
return (
<p>收到参数:{match.params.p}</p>
)
}
export default withRoute(App);
一个例子

【完】

浙公网安备 33010602011771号