javascript
<BrowserRouter>
<Routes>
<Route index element={<Homepage />} />
<Route path="product" element={<Product />} />
<Route path="pricing" element={<Pricing />} />
<Route path="login" element={<Login />} />
<Route
path="app"
element={
<ProtectedRoute>
<AppLayout />
</ProtectedRoute>
}
>
<Route index element={<Navigate replace to="cities" />} />
<Route path="cities" element={<CityList />} />
<Route path="cities/:id" element={<City />} />
<Route path="countries" element={<CountryList />} />
<Route path="form" element={<Form />} />
</Route>
<Route path="*" element={<PageNotFound />} />
</Routes>
</BrowserRouter>
BrowserRouter
BrowserRouter
是 React Router 提供的一个组件,利用 HTML5 的历史 API 来保持用户界面(UI)与 URL 的同步。下面详细解释这一机制是如何实现的。
实现原理
1. HTML5 History API
BrowserRouter
主要依赖于 HTML5 的 history
对象,该对象提供了以下几个重要方法:
pushState(state, title, url)
: 这个方法用于向浏览器的历史记录中添加一个新的条目。调用此方法后,URL 将更新,但页面不会重新加载。replaceState(state, title, url)
: 此方法与pushState
类似,但它替换当前的历史记录条目,而不是添加新的条目。popstate
事件 : 当用户点击浏览器的前进或后退按钮时,会触发popstate
事件。这允许应用程序检测到 URL 的变化并作出相应的反应。
2. URL 与 UI 的同步
当使用 BrowserRouter
时,React Router 会监听 URL 的变化,并根据当前的 URL 渲染相应的组件。具体步骤如下:
- 初始化 : 当应用程序加载时,
BrowserRouter
会读取当前的 URL,并根据路由配置渲染相应的组件。 - 用户交互 : 当用户通过点击链接(例如使用
<Link>
组件)进行导航时,React Router 会调用pushState
或replaceState
方法来更新浏览器的地址栏,而不重新加载页面。 - 处理历史记录 : 当用户使用浏览器的前进或后退按钮时,
popstate
事件会被触发。React Router 会监听这个事件,并根据新的 URL 更新渲染的组件。
Routes
Routes
是一个容器,用于定义应用程序中的所有路由。它会根据当前 URL 渲染相应的 Route
组件。
Route
默认路由
javascript
<Route index element={<Homepage />} />
该Route
定义了一个特定路径的组件。这里的 index
属性表示当用户访问根路径时(例如 /
),将渲染 Homepage
组件。
定义路由
javascript
<Route path="product" element={<Product />} />
<Route path="pricing" element={<Pricing />} />
<Route path="login" element={<Login />} />
这些Route
元素指定了一个URL 路径和对应的组件。当用户访问这些路径时,会渲染相应的组件。例如,访问 /product
时会显示 Product
组件。
受保护的路由
javascript
<Route
path="app"
element={
<ProtectedRoute>
<AppLayout />
</ProtectedRoute>
}
>
这个路由使用了一个名为 ProtectedRoute
的组件,通常用于保护某些页面,确保只有经过身份验证的用户才能访问。在这个例子中,只有在通过 ProtectedRoute
验证后,才能访问包含在 AppLayout
中的子路由。
javascript
<Route index element={<Navigate replace to="cities" />} />
<Route path="cities" element={<CityList />} />
<Route path="cities/:id" element={<City />} />
<Route path="countries" element={<CountryList />} />
<Route path="form" element={<Form />} />
这些路由是上面路由的子路由。
Navigate组件
javascript
<Route index element={<Navigate replace to="cities" />} />
作用
- 重定向 :
<Navigate>
组件用于将用户从一个路由重定向到另一个路由。在这个例子中,它将用户重定向到cities
路径。
属性
to
: 这是目标路径,表示用户将被重定向到哪里。在这个例子中,to="cities"
表示用户将被重定向到/cities
路径。replace
: 这是一个布尔属性,如果设置为true
,则会使用history.replace()
方法来替换当前的历史记录条目,而不是添加新的条目。这意味着用户在浏览器中点击"后退"按钮时,不会返回到重定向前的页面。
使用场景
- 条件导航: 在某些情况下,例如用户未登录时,可能希望将他们重定向到登录页面;或者在访问某个页面后立即重定向到另一个页面。
- 默认路由 : 在嵌套路由中,可以使用
<Navigate>
来设置默认路由。例如,在访问/app
时,可以立即重定向到/app/cities
。
动态路由
javascript
<Route path="cities/:id" element={<City />} />
id
是一个动态参数,它表示在访问该路由时,URL 中的具体值将被捕获并传递给渲染的组件。
具体解释
- 动态参数 :
:id
是一个占位符,用于匹配 URL 中的特定部分。当用户访问类似/cities/1
或/cities/42
的 URL 时,:id
将匹配到1
或42
,并将其作为参数传递给相应的组件。
- 访问参数 :
-
在
City
组件中,可以使用 React Router 提供的useParams
钩子来获取这个动态参数。例如:javascriptimport { useParams } from "react-router-dom"; function City() { const { id } = useParams(); ... }
-
这样,当用户访问
/cities/1
时,id
的值将为1
,而当访问/cities/42
时,id
的值将为42
。
-
404错误
javascript
<Route path="*" element={<PageNotFound />} />
使用 path="*"
匹配所有未定义的路径,并渲染 PageNotFound
组件。这是处理404错误页面的常见方式。
补充:
javascript
const navigate = useNavigate()
navigate(`form?lat=${e.latlng.lat}&lng=${e.latlng.lng}`);
javascript
const [searchParams] = useSearchParams();
const lat = searchParams.get("lat");
const lng = searchParams.get("lng");
通过这种方式可以实现再URL存储传递全局state