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