React - Router的基本使用介绍
目前前端流行的三大框架, 都有自己的路由实现:
Angular的ngRouter
React的ReactRouter
Vue的vue-router
React Router在最近两年版本更新的较快,并且在最新的React Router6.x版本中发生了较大的变化。
目前React Router6.x已经非常稳定,我们可以放心的使用;
说明一下, Router4.x和Router5.x的区别是不大的, 而Router6.x就有些区别, 所以Router系列的文章主要针对Router6.x进行讲解, 当有与4或5版本不同的地方时会单独强调
安装React Router:
安装时,我们选择安装react-router-dom, npm install react-router-dom;
因为react-router会包含一些react-native的内容,web开发并不需要;
Router的组件API
react-router最主要的API是给我们提供的一些组件:
BrowserRouter或HashRouter
Router中包含了对路径改变的监听,并且会将相应的路径传递给子组件;
BrowserRouter使用history模式;
import React from "react" import ReactDOM from "react-dom/client" import { BrowserRouter } from "react-router-dom" import App from "./App" const root = ReactDOM.createRoot(document.querySelector("#root")) root.render( <BrowserRouter> <App/> </BrowserRouter> )HashRouter使用hash模式
import React from "react" import ReactDOM from "react-dom/client" import { HashRouter } from "react-router-dom" import App from "./App" const root = ReactDOM.createRoot(document.querySelector("#root")) root.render( <HashRouter> <App/> </HashRouter> )Router的映射配置
Routes:包裹所有的Route,在其中匹配一个路由
Router6.x使用的是Routes组件
Router5.x使用的是Switch组件
Route:Route用于路径的匹配;
Router6.x不允许Router组件单独存在
path属性: 用于设置匹配到的路径;
element属性: 设置匹配到路径后,渲染的组件;
Router5.x使用的是component属性exact: 精准匹配,只有精准匹配到完全一致的路径,才会渲染对应的组件;
Router6.x不再支持该属性 <div className='app'> <div className='header'>header</div> <div className='counter'> <Routes> <Route path='/' element={<Home/>}/> <Route path='/about' element={<About/>}/> <Route path='/profile' element={<Profile/>}/> </Routes> </div> <div className='footer'>footer</div> </div>Router配置和跳转
Link组件:
通常路径的跳转是使用Link组件,这个组件最终会被渲染成a元素;
NavLink是在Link基础之上增加了一些样式属性(后续会讲解);
to属性: Link中最重要的属性,用于设置跳转到的路径
例如实现上面代码, 我们在header中实现点击按钮切换页面的效果
<div className='app'> <div className='header'> <Link to="/">首页</Link> <Link to="/about">关于</Link> <Link to="/profile">我的</Link> </div> <div className='counter'> <Routes> <Route path='/' element={<Home/>}/> <Route path='/about' element={<About/>}/> <Route path='/profile' element={<Profile/>}/> </Routes> </div> <div className='footer'>footer</div> </div>NavLink组件
需求:路径选中时,对应的a元素的文字变为红色
这个时候,我们要使用NavLink组件来替代Link组件, NavLink组件选中时, 有添加一个类(这个组件了解即可, 不如自己控制更方便):
事实上在默认匹配成功时,NavLink就会动态的添加上一个class: active , 选中的时候就会添加;
所以我们也可以直接编写样式
当然,如果你担心这个class在其他地方被使用了,出现样式的层叠,也可以自定义class和动态添加样式
style属性: 传入一个函数,函数的参数接收一个对象,该对象包含isActive属性
<NavLink to="/" style={({ isActive }) => ({color: isActive ? "red" : ""})}>首页</NavLink> <NavLink to="/about" style={({ isActive }) => ({color: isActive ? "red" : ""})}>关于</NavLink> <NavLink to="/profile" style={({ isActive }) => ({color: isActive ? "red" : ""})}>我的</NavLink>className:传入一个函数,函数的参数接受一个对象,该对象包含isActive属性
<NavLink to="/" className={({ isActive }) => isActive ? "my-class" : ""}>首页</NavLink> <NavLink to="/about" className={({ isActive }) => isActive ? "my-class" : ""}>关于</NavLink> <NavLink to="/profile" className={({ isActive }) => isActive ? "my-class" : ""}>我的</NavLink>Navigate组件使用
Navigate用于路由的重定向,当这个组件出现时,就会执行跳转到对应的to路径中:
我们这里使用这个的一个案例:
用户跳转到Profile界面;
但是在Profile界面有一个isLogin用于记录用户是否登录:
true: 表示已登录, 跳转到首页;false: 表示未登录, 显式登录按钮; export class Profile extends PureComponent { constructor(props) { super(props) this.state = { isLogin: false } } login() { this.setState({ isLogin: true }) } render() { const { isLogin } = this.state console.log(isLogin) return ( <div> <h2>Profile</h2> {/* 为true时重定向到首页 */} {isLogin ? <Navigate to="/home" /> : <button onClick={() => this.login()}>登录</button>} </div> ) } }我们也可以在匹配到 “/” 的时候,直接跳转到 “/home” 页面
<Routes> {/* 当默认路径 / 时, 重定向到home页面 */} <Route path='/' element={<Navigate to="/home"/>}></Route> <Route path='/home' element={<Home/>}/> <Route path='/about' element={<About/>}/> <Route path='/profile' element={<Profile/>}/> </Routes>Not Found页面配置
如果用户随意输入一个地址,该地址无法匹配,那么在路由匹配的位置将什么内容都不显示。
很多时候,我们希望在这种情况下,让用户看到一个Not Found的页面。
这个过程非常简单:
开发一个Not Found页面;
配置对应的Route,并且设置path为*即可;
<Routes> {/* 当默认路径 / 时, 重定向到home页面 */} <Route path='/' element={<Navigate to="/home"/>}></Route> <Route path='/home' element={<Home/>}/> <Route path='/about' element={<About/>}/> <Route path='/profile' element={<Profile/>}/> {/* 当上面路径都没有匹配到时, 显式Notfound组件 */} <Route path='*' element={<Notfound/>}/> </Routes>