插件安装
npm add react-router-dom
react-router-dom
:主要用于在 Web 应用中实现路由功能,提供了如 BrowserRouter
、Link
、Route
等与浏览器环境相关的组件和功能。
react-router-native
:用于 React Native 应用的路由,与 react-router-dom
类似,但针对移动应用场景进行了适配和调整。
基础示例
创建app1和app2两个组件, 通过路由来控制切换
import {createBrowserRouter, RouterProvider} from 'react-router-dom'
const App1 = () => <div>this is app1</div>
const App2 = () => <div>this is app2</div>
const router = createBrowserRouter([
{
path: '/app1',
element: <App1 />
},
{
path: '/app2',
element: <App2 />
}
])
export default () => {
return (
<RouterProvider router={router}></RouterProvider>
)
}
使用 createBrowserRouter
函数来创建一个路由配置对象 router
,然后使用 RouterProvider
组件将这个配置对象提供给整个应用程序。
补充
createBrowserRouter
和 createHashRouter
都是 React Router 库中的函数,用于创建不同类型的路由器实例。它们之间的主要区别在于它们管理 URL 的方式。
createBrowserRouter: createBrowserRouter
使用 HTML5 的 history API 来管理 URL。这意味着当用户在应用中导航时,URL 会被更新,并且用户可以使用浏览器的前进和后退按钮来导航历史记录。这种方式提供了一个更友好的用户体验,并且对 SEO 也更友好。它适用于大多数现代 Web 应用。
createHashRouter: createHashRouter
使用 URL 的 hash 部分(#
后面的部分)来管理路由。这意味着 URL 的改变不会导致页面刷新,因为 hash 的改变不会被服务器识别。这种方式在一些特定场景下有用,比如需要支持旧版浏览器,或者在开发过程中需要避免服务器配置的复杂性。但是,它对 SEO 不友好,因为搜索引擎通常不会索引 #
后面的内容。
项目结构
上面是路由的简单也是最基础的使用方式, 一般在项目中我们会创建单独的文件夹来管理所有的路由相关的操作
src
├── pages
| ├── App1
| └── App2
└── router
└── index
- pages目录存放页面
- router 目录下存放路由相关
我们按照你这个结构把上面的事例拆分一下
import { createBrowserRouter } from "react-router-dom";
import App1 from "../pages/App1/index";
import App2 from "../pages/App2/index";
const router = createBrowserRouter([
{
path: "/",
element: <App1 />
},
{
path: "/app2",
element: <App2 />
}
])
export default router;
const App1 = () => {
return (
<div>
<h1>App1</h1>
</div>
)
}
export default App1
上面我们分别定义了router.tsx和页面app1, app2与app1相同。 但同时我们还需要到入口处进行路由的引用改造。
import React from 'react';
import ReactDOM from 'react-dom/client';
import router from './router';
import { RouterProvider } from 'react-router-dom'
const root = ReactDOM.createRoot(document.getElementById('root')!);
root.render(
<React.StrictMode>
<RouterProvider router={router}></RouterProvider>
</React.StrictMode>,
);
嵌套
还是上面的示例, 现在在app1这个页面, 嵌入app3. 我们先去router列表路面嵌套
import { createBrowserRouter } from "react-router-dom";
import App1 from "../pages/App1/index";
import App2 from "../pages/App2/index";
import App3 from "../pages/App3/index";
const router = createBrowserRouter([
{
path: "/",
element: <App1 />,
children: [
{
path: 'app3',
element: <App3 />
}
]
},
{
path: "/app2",
element: <App2 />
}
])
export default router;
然后在app1 页面提供路由的出口
import { Outlet } from 'react-router-dom'
const App1 = () => {
return (
<div>
<h1>App1</h1>
<Outlet />
</div>
)
}
export default App1
根据router我们的访问地址应该是http://127.0.0.1:3000/app3
路由导航
上面路由通过手动在地址栏切换已经可以看到效果, 但一般我们在系统内进行切换,,都是通过导航交互进行的
导航链接
import { Outlet, Link } from 'react-router-dom'
const App1 = () => {
return (
<div>
<h1>App1</h1>
<Link to="/app3">to app3</Link>
<Outlet />
</div>
)
}
export default App1
<Link>
组件用于在React
应用中创建导航链接,允许用户在不同的路由之间导航。
Link
组件的to
属性,用于指定用户点击链接时应导航到的路径。在这个例子中,/app3
代表应用程序中的一个特定路径。
此外,<Link>
组件还提供了replace
、state
等其他属性
编程式导航
import { useNavigate } from 'react-router-dom'
const App3 = () => {
const navigate = useNavigate()
return (
<div>
<h1 onClick={() => navigate('/app2') }>App3</h1>
</div>
)
}
export default App3
useNavigate
是 react-router-dom
库提供的一个钩子(hook
),它允许你在组件中编程式地导航到不同的路由。当你调用 useNavigate()
时,它会返回一个函数,你可以使用这个函数来导航到应用中的不同页面或路径。
传参
方式一
传递
<Link to="/app3?id=101&name=zhangsan">to app3</Link>
接收
import { useNavigate, useSearchParams } from 'react-router-dom'
const App3 = () => {
const navigate = useNavigate()
const [searchParams, setSearchParams] = useSearchParams()
const id = searchParams.get('id')
const name = searchParams.get('name')
return (
<div>
<h1 onClick={() => navigate('/app2') }>App3</h1>
<span>id: {id}</span>
<span>name: { name }</span>
</div>
)
}
export default App3
调用 useSearchParams
用来获取当前 URL 的查询参数。该函数会返回一个包含所有查询参数的对象,searchParams
以及一个可以用来设置查询参数的函数 setSearchParams
。这样,组件就可以读取 URL 中传递的查询参数,也可以通过 setSearchParams
函数修改这些参数,从而实现更新 URL,并在应用中导航到新的路径或状态。
setSearchParams
函数的使用可能稍微复杂一些,因为它需要一个新的查询参数字符串或者一个对象来表示新的参数。在设置参数时,你可以传递整个字符串:
setSearchParams('?id=101&name=zhangsan');
:或者一个对象
setSearchParams({
id: '101',
name: 'zhangsan'
});
例如,在点击事件处理程序中,你可以使用 setSearchParams
函数导航到 App2
并传递新的查询参数:
import { useNavigate, useSearchParams } from'react-router-dom';
const App3 = () => {
const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams();
const handleClick = () => {
setSearchParams({
id: '101',
name: 'zhangsan'
});
navigate('/app2');
};
return (
<div>
<h1 onClick={handleClick}>App3</h1>
</div>
);
};
export default App3;
在这个例子中,当用户点击 App3
标题时,handleClick
函数会被调用。它会先设置查询参数,然后使用 navigate
函数导航到 /app2
路径。App2
组件可以通过 useSearchParams
获取设置的查询参数。
方式二
传递
<Link to="/app2/101/zhangsan">to app2</Link>
这种方式我们还需要修改一下路由
{
path: "/app2/:id/:name",
element: <App2 />
}
接收
import { useParams } from 'react-router-dom'
const App2 = () => {
const params = useParams()
return (
<div>
<h1>App2</h1>
<span>id: {params.id }</span>
<span>name: { params.name }</span>
</div>
)
}
export default App2
对比
useParams
和 useSearchParams
是两个不同的获取参数的钩子,它们用于从当前的 URL 中提取不同类型的信息:
useParams: useParams
钩子用于获取 URL 中的路由参数。当你在 React Router
中定义了路由配置,并在路径中使用了参数化的语法,比如 /user/:id
,你可以使用 useParams
来获取 id
的值。这个钩子返回一个对象,其中包含了所有路由参数的键值对。例如,在 /user/123
的 URL 中,useParams
将返回 { id: '123' }
。
useSearchParams: useSearchParams
钩子用于获取 URL 中的查询参数。查询参数是在 URL 问号后面的部分,通常用于传递额外的信息,比如筛选条件、排序方式等。useSearchParams
返回一个包含所有查询参数的数组。每个参数都是一个包含 name
和 value
键的对象。例如,在 ?id=101&name=zhangsan
的 URL 中,useSearchParams
将返回一个包含两个对象的数组:[{ name: 'id', value: '101' }, { name: 'name', value: 'zhangsan' }]
。 与 useParams
不同,useSearchParams
还提供了一个函数 setSearchParams
,允许你通过编程方式设置查询参数,从而改变 URL。