目录
2.6.2 编程式导航 (注意HOOK使用 类组件不可以直接使用)
<Route> 特性变更
path:与当前页面对应的URL匹配。
element:新增,用于决定路由匹配时,渲染哪个组件。代替v5的component和render。
useNavigate代替useHistory
移除了
钩子useRoutes代替react-router-config
移除了exact
路由官网:https://reactrouter.com/en/v6.3.0/api
引入最新的reac-router-dom
$ yarn add react-router-dom@6
npm
$ npm install react-router-dom@6
目前安装react项目 默认已经是v6版本了 不需要特殊加版本号
我这里引入的是HashRouter,还有一种BrowserRouter
- import React from 'react';
- import ReactDOM from 'react-dom/client';
- import App from './App';
- import { BrowserRouter,HashRouter } from "react-router-dom";
- const root = ReactDOM.createRoot(document.getElementById('root'));
- root.render(
- <BrowserRouter>
- <App />
- BrowserRouter>
-
- );
- <Routes>
- {/*<Route path="/" element={<Film/>}/>*/}
- <Route index element={<Film/>}/>
- <Route path="/film" element={<Film/>}/>
- <Route path="/cinema" element={<Cinema/>}/>
- <Route path="/center" element={<Center/>}/>
- </Routes>
- index用于嵌套路由,仅匹配父路径时,设置渲染的组件。
- 解决当嵌套路由有多个子路由但本身无法确认默认渲染哪个子路由的时候,可以增加index属性来指定默认路由。
- <Routes>
- <Route path="/film" element={<Film />} />
- <Route path="/cinema" element={<Cinema />} />
- <Route path="/center" element={<Center />} />
- <Route path="*" element={<Navigate to="/film" />} />
- </Routes>
- <Route path="/film" element={<Film/>}>
- {/* <Route index element={<Nowplaying/>}/> */}
- <Route path="" element={<Redirect to="/film/nowplaying"/>}/>
- <Route path="nowplaying" element={<Nowplaying/>}/>
- <Route path="comingsoon" element={<Comingsoon/>}/>
- </Route>
-
- // Film组件 <Outlet /> 相当于 <router-view />
- <NavLink to='/'>首页</NavLink> |
- <NavLink to='/news'>新闻</NavLink> |
- <NavLink to='/about'>我的</NavLink> |
- <NavLink to='/detail/123'>详情界面</NavLink>
- // url传参
- const navigate = useNavigate()
- navigate(`/detail?id=${id}`)
- // 获取url参数
- import { useSearchParams } from 'react-router-dom'
-
- const [searchParams, setSearchParams] = useSearchParams()
- // 获取参数
- searchParams.get('id')
- // 判断参数是否存在
- searchParams.has('id')
- // 同时页面内也可以用set方法来改变路由
- setSearchParams({"id":2})
- // 跳转页面,路由传参
- navigate(`/detail/${id}`)
-
- // 配置动态路由
- <Route path="/detail/:id" element={<Detail />}/>
-
- // 获取动态路由参数
- import { useParams } from 'react-router-dom'
- const { id } = useParams()

发现props是一个空对象!!! 这样很多的功能根本通过路由参数实现不了了,比如:
编程式路由导航,在非受控组件中可以使用useNavigate这个钩子进行导航,而在类组件中无能为力,只能想办法使用
获取路由参数 ,在以往的react-router-dom版本中,路由的三个参数location、history、match都是直接挂载到组件的props身上,即使组件不是路由组件,也可以使用withRouter高阶组件对普通组件进行增强,也可以将这三个参数带到props身上。
在v6版本中withRouter直接被移除。怎么办?
估计官方的目的是极力推荐我们使用React Hooks ,从而提高类组件的使用门槛(tm不能像vue那样做做兼容,平滑过度吗?)。只能自己编写高阶组件withRouter从而实现这一需求,可以看看这篇文章中的回答:https://cloud.tencent.com/developer/ask/sof/296970
- // 获取动态路由参数
- import { useNavigate,useLocation,useParams } from 'react-router-dom'
-
- export function withRouter( Child ) {
- return ( props ) => {
- const location = useLocation();
- const navigate = useNavigate();
- const params = useParams()
- // const match= useMatch()
- return <Child params={params} navigate={ navigate } location={ location } />;
- }
- }
组件使用的时候
- import React, { Component } from 'react'
- // 获取动态路由参数
- import {withRouter} from './withRouter'
- class Detail extends Component {
- constructor(){
- super()
- }
- render() {
- console.log(this);
- return (
- <div>Detail
- <p>参数:{this.props.params.id}</p>
- </div>
- )
- }
- }
- export default withRouter(Detail)
App.js组件路由配置
- import Home from './views/Home'
- import News from './views/News'
- import About from './views/About'
- import One from './views/Today'
- import Two from './views/Yestoday'
- import Detail from './views/Detail'
- import './app.css'
- //配置路由
- import { Route, Link, Routes, BrowserRouter,NavLink,Navigate ,Outlet} from 'react-router-dom'
- function App() {
- return (
- <>
- <div>
- <NavLink to='/'>首页</NavLink> |
- <NavLink to='/news'>新闻</NavLink> |
- <NavLink to='/about'>我的</NavLink> |
- <NavLink to='/detail/123'>详情界面</NavLink>
- <Outlet/>
- </div>
-
- <Routes>
- {/* <Route path="/" element={<Home />}></Route> */}
- <Route index element={<Home />}></Route>
- <Route path="home" element={<Home />}></Route>
- {/* // 配置动态路由 */}
- <Route path="detail/:id" element={<Detail />}/>
- {/* 路由嵌套 */}
- <Route path="news" element={<News />}>
- {/* 二级路由 */}
- {/*
- index用于嵌套路由,仅匹配父路径时,设置渲染的组件。
- 解决当嵌套路由有多个子路由但本身无法确认默认渲染哪个子路由的时候,可以增加index属性来指定默认路由。
- index路由和其他路由不同的地方是它没有path属性,他和父路由共享同一个路径。
- */}
- <Route index element={<One/>}></Route>
- <Route path='one' element={<One/>}></Route>
- <Route path='two' element={<Two />}></Route>
- </Route>
- <Route path="about" element={<About />}></Route>
- {/* //当输入 /* 任意信息,重定向到首页 */}
- <Route path='*' element={<Navigate replace to="/home" />} />
- </Routes>
- </>
- );
- }
-
- export default App;
样式
在V6 版本中activeClassName 和activeStyle 已经从NavLinkProps中移除,可以直接在<NavLink>的className和style中使用一个函数来使用active。
V5:
- <NavLink to="/faq" activeClassName="selected">
- FAQs
- </NavLink>
V6
- let activeClassName = "underline"
- <NavLink
- to="/faq"
- className={({ isActive }) =>
- isActive ? activeClassName : undefined
- }
- >
- FAQs
- </NavLink>
- import React from "react";
- import Layout from '../views/Layout'
- import Home from '../views/Home'
- import News from '../views/News'
- import About from '../views/About'
- import One from '../views/Today'
- import Two from '../views/Yestoday'
- import Detail from '../views/Detail'
-
- const routes=[
- {
- path:'/',
- element:<Layout/>,
- children:[
- {
- path:'/',
- element:<Home/>,
- },
- {
- path:'/detail/:id',
- element:<Detail/>,
- },
- {
- path:'/about',
- element:<About/>,
- },
- {
- path:'/news',
- element:<News/>,
- children:[
- { index: true, element: <One /> },
- { path: "one", element: <One /> },
- { path: "two", element: <Two /> }
- ]
- }
- ]
-
- }
- ]
-
- export default routes
app.js使用
-
- import { useRoutes } from "react-router-dom";
- import routes from './router/routes'
- function App() {
- const element = useRoutes(routes);
-
- return (
- <>
- {element}
- >
-
- );
- }
-
- export default App;
Switch -> Routers

Router component -> element
<Route path='/admin/dashboard' component={Dashboard} />
<Route path=":id" element={<UserProfile />} />
重定向
- //v5
- <Redirect to="about" />
- <Redirect to="home" push />
-
- // v6
- <Navigate to="about" replace />
- <Navigate to="home" />

Router 可以直接嵌套 Router
这在之前是不行的需要在一个组件中再定义子路由

路由路径规则简化
useHistory成为History

- v5
-
- let history = useHistory();
- function handleClick() {
- history.push("/home");
- }
-
- v6
-
- let navigate = useNavigate();
- function handleClick() {
- navigate("/home");
- }
- //v5
- const { go, goBack, goForward } = useHistory();
- //v6
- const navigate = useNavigate();
- <button onClick={() => navigate(1)}>
- <button onClick={() => navigate(2)}>
- <button onClick={() => navigate(-1)}>
- <button onClick={() => navigate(-2)}>
重命名
useMatch -> useRouteMatch
