引言
大家好,我是你们的程序猿老朋友,今天咱们来聊聊 React 开发中不可或缺的灵魂伴侣------React Router!
🧐 为啥需要路由?
想象一下,如果你的网站只有一个页面,所有内容都挤在一起,那会是怎样一种灾难?就像把所有水果都塞进一个袋子,西瓜压坏了苹果,香蕉被挤成了泥...😱 为了让我们的应用井井有条,结构清晰,路由应运而生!它就像一个交通指挥官,根据不同的 URL,把用户带到不同的页面。
小 Tips: 路由驱动应用,就像一个精密的时钟,每个齿轮的转动都至关重要。
🛠️ React Router:组件化路由的扛把子
就像 React 是组件化的王者,React Router 也秉承了这一优良传统。它把路由的概念也组件化了,让我们的代码更加易读、易维护。
1. 安装 "全家桶" 必备:
npm install react-router-dom
首先,我们需要安装 react-router-dom
这个包,它包含了我们实现路由所需要的一切。
2. 路由定义大舞台:router/index.jsx
jsx
import {
BrowserRouter,
Route,
Routes,
} from 'react-router-dom'
import App from '../App'
import About from '../pages/About.jsx'
import Home from '../pages/Home.jsx'
import NotFound from '../pages/NotFound.jsx'
import { postRouter } from '../pages/post/postRouter.jsx'
const AppRouter = () => {
return (
<BrowserRouter>
<Routes>
<Route path='/' element={<App />} >
<Route index element={<Home />} />
<Route path='about' element={<About />} />
<Route path="posts/*" element={postRouter} />
<Route path='*' element={<NotFound />} />
</Route>
</Routes>
</BrowserRouter>
)
}
export default AppRouter
-
<BrowserRouter>
: 这是路由的"地基",它能让你的应用支持 HTML5 的pushState
API,从而实现漂亮的 URL 切换。 -
<Routes>
: 它就像一个"路由匹配器",它会遍历<Route>
标签,找到与当前 URL 匹配的路由,并渲染对应的组件。 -
<Route>
: 每一个<Route>
标签都代表一条路由规则。path
属性定义了 URL 的路径,element
属性指定了要渲染的组件。index
属性: 当父路由路径和当前路由路径相同时,渲染此属性的组件。path="*"
: 通配符,当所有路由都不匹配时,渲染此路由组件,通常用于渲染 404 页面。- 嵌套路由: 在父路由
<Route>
中再嵌套<Route>
,实现父子组件的嵌套渲染,如示例中 posts 就是嵌套路由。
小 Tips: BrowserRouter
就像你的大船,<Routes>
是你的航线图,<Route>
是你的一个个港口,带你抵达想去的地方。 ⛵️
3. 页面组件:你的内容展示区
-
About.jsx
jsximport { useEffect } from "react" import { Link } from 'react-router-dom' const About = () => { useEffect(() => { document.title = 'About' }, []) return ( <div> <h1>About</h1> <Link to='/'>回到首页</Link> </div> ) } export default About
useEffect
: 它是一个 React Hooks,我们用来在组件挂载后执行一些操作,比如在这里,我们修改了页面的标题。Link
: 这是 React Router 提供的导航组件,它会生成一个<a>
标签,点击它会触发路由切换,注意这里和普通的<a>
标签不一样,他不会刷新页面,这也是SPA应用的优点。
-
Home.jsx
jsximport { useEffect } from "react" const Home = () => { useEffect(() => { document.title = 'Home' }, []) return ( <div> <h1>Home</h1> <div>你好</div> </div> ) } export default Home
-
NotFound.jsx
(这一部分会有点复杂o)jsximport { useState, useEffect } from "react" const NotFound = () => { const [count, setCount] = useState(0) useEffect(() => { console.log('title执行了'); document.title = 'Not Found' return () => { console.log('title卸载了'); } }, []) const add = () => { setCount(count + 1) } useEffect(() => { console.log('count更新了'); }, [count]) return ( <div> <h1 onClick={add}>404</h1> </div> ) } export default NotFound
-
useState
: 组件的状态管理,像 Vue 的data
!useState
就像一个简易的记事本,用来记录组件的数据。例如,const [count, setCount] = useState(0)
就相当于 Vue 的data
中定义了count: 0
,你可以用setCount
更新count
的值。 -
useEffect
: 副作用处理,React 的生命周期钩子!-
第一个参数:副作用函数,类似 Vue 的
mounted
+updated
!useEffect(() => { /* ... */ })
里的函数会在组件首次渲染后执行,也会在更新后执行,相当于 Vue 的mounted
和updated
的结合体。 -
第二个参数(可选):依赖项数组,类似 Vue 的
watch
!useEffect(() => { /* ... */ }, [count])
表示只有count
变化时,副作用函数才会执行,相当于 Vue 的watch
监听count
的变化。 -
返回值(可选):清理函数,类似 Vue 的
beforeUnmount
!useEffect(() => { return () => { /* ... */ } })
返回的函数会在组件卸载前执行,用于清理副作用,类似于 Vue 的beforeUnmount
钩子。
-
小小总结一下:
-
useState
:管理组件状态,类似 Vue 的data
。 -
useEffect
:处理副作用,类似 Vue 的生命周期钩子:- 无第二个参数,类似
mounted
+updated
。 - 有第二个参数,类似
watch
。 - 返回值,类似
beforeUnmount
。
- 无第二个参数,类似
-
主页面
App.jsx
jsximport './App.css' import { Outlet, NavLink } from "react-router-dom" function App() { return ( <> <header> <nav> <NavLink to='/'>Home</NavLink> <NavLink to='/about'>About</NavLink> </nav> </header> <Outlet /> </> ) } export default App
-
Outlet
: 它就像一个"占位符",用来渲染嵌套路由的子组件,在这里,他用来渲染Home和About组件。 -
NavLink
: 它是Link
的升级版,当它对应的路由被激活时,会自动添加active
类名,方便你设置高亮样式。NavLink
和a
标签的区别:NavLink
会阻止页面刷新,通过 React Router 实现页面跳转,而a
标签会刷新整个页面。NavLink
就像一辆飞速的跑车,而a
标签则是一辆略显笨拙的老爷车。 🚗NavLink
的优势:- 不会刷新页面,提高用户体验。
- 支持高亮样式,方便用户知道当前所在页面。
-
小 Tips: 页面组件是你的舞台,路由帮你把观众带到这里,而 Outlet
则是你表演的焦点! 🎭
4. 嵌套路由:post
文件夹下的内容,这一部分你可以当成我们要进行一个更深的页面跳转
jsx
// postRouter.jsx
import {
Route, Routes
} from "react-router-dom";
import PostIndex from './Post-Index.jsx';
import PostShow from './Post-Show.jsx';
export const postRouter = (
<Routes>
<Route path='' element={<PostIndex />} />
<Route path=':postid' element={<PostShow />} />
</Routes>
)
// Post-Index.jsx
const PostIndex = () => {
return (
<div>
<h1>PostIndex</h1>
</div>
)
}
export default PostIndex
// Post-Show.jsx
import { useEffect } from "react"
import { useParams } from "react-router-dom"
const PostShow = () => {
const { postid } = useParams()
useEffect(() => {
document.title = `Post-${postid}`
}, [])
return (
<div>
<h1>PostShow</h1>
</div>
)
}
export default PostShow
useParams
: 这是一个 React Router Hooks,用来获取路由参数,在这里,我们用它来获取动态的postid
。(注意一下哦这个参数的名字要和动态路由(:postid)
的名字一样哦)
小 Tips: 嵌套路由就像俄罗斯套娃,一层套一层,让你的应用更加灵活和模块化。 🪆
总结
好啦,关于 React Router 的精彩旅程就先到这里啦!希望这篇博客能帮助你更好地理解 React Router 的原理和用法。记住,React Router 是你构建复杂 React 应用的利器,它可以让你轻松实现页面跳转和嵌套路由,让你的应用焕发新的生机!
如果你觉得这篇文章对你有帮助,别忘了点赞、分享和收藏哦!
下次见! 👋