小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言:
一个很简单的需求,React 的单页应用,要求站点内 URL不匹配时跳转到单独的404页面。
一开始以为是个很简单就搞定的问题(实际上就是个很简单的问题,只是个人经验不足),结果研究了好几天居然没解决。
特此记录一下思路。
效果:
地址栏输入站内不存在的 URL 效果一样。
react-router-dom 官网上的,还是网上搜索到的,大多是下面这种写法。
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/old-match">
<Redirect to="/will-match" />
</Route>
<Route path="/will-match">
<WillMatch />
</Route>
<Route path="*">
<NoMatch />
</Route>
</Switch>
上面代码复制自react-router-dom 官网:
各个路由对应各自的组件,没有对应组件的路由,path 设置为*,意思为上面路由之外的所有路由,都使用404的组件(上例中是 NoMatch)。
不匹配时显示效果如下:
这样的404实际上还是在主业务页面里,把业务区域的显示内容置换为404页面的内容,所以还带着菜单。
大多数情况下,想要跳转的是一个单独的404页面,完全和主业务页面独立。
思路如下,嵌套路由,主业务页面和404页面是平级关系,主业务页面里是原来的处理方式,点击菜单显示不同的子页面。
访问不存在的路由时,重定向到404页面。
代码如下:
使用 create-react-app 创建的工程
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter basename="helloreact">
<App />
</BrowserRouter>,
document.getElementById('root')
);
App.js
import React from 'react';
import { Route, Switch } from 'react-router';
import Home from './home.jsx';
import './App.css';
function App() {
return (
<Switch>
<Route path="/404" exact>
<div>404</div>
</Route>
<Route path="/">
<Home></Home>
</Route>
</Switch>
);
}
export default App;
App.js 里是父级路由,这里优先匹配404,匹配后显示404页面。
然后需要定义匹配/的路由,匹配时显示的组件为主业务页面。
home.jsx
import { Redirect, Route, Switch, Link } from "react-router-dom";
function Home() {
return (
<>
<ul>
<ul><Link to="/home">Home</Link></ul>
<ul><Link to="/about">About</Link></ul>
<ul><Link to="/nomatch">No Router</Link></ul>
</ul>
<Switch>
<Route path="/" exact>
<div>Home</div>
</Route>
<Route path="/home" exact>
<div>Home</div>
</Route>
<Route path="/about" exact>
<div>About</div>
</Route>
<Redirect path="*" to="/404"></Redirect>
</Switch>
</>
);
}
export default Home;
主页里定义子路由,点击可匹配的路由时,显示区域里(菜单之外)显示对应的组件。
例如,这里点击 Home 时,路由为 /home,就会显示 Home 。
然后当不匹配时,不再使用<Route path="*"> 的写法,而是使用 Redirect 重定向到 404,这样就会在没有匹配的路由时,父级路由匹配404,然后显示一个单独的404页面。