react-router v6 尝鲜心得

2,081 阅读4分钟

公司开了个新的前端react项目,在创建项目的时候试着用了react-router的v6版本,不用不知道,一用吓一跳。我熟悉的Switch呢? Redirect呢?的component/render也不见了?心想我是不是下载错版本了,一看版本号也没啥问题,转头就去啃源码。。。经过一番消化后,心想我去,真香。。。。。。

首先我本次使用的是hooks写法,类写法是否适用目前还没验证,和我使用同样写法的同学可以继续关注下。。。

React Router库中的不同软件包

react-router-domreact-router-native, 程序包 react-router 是核心库,用作上面列出的他两个程序包的对等依赖项。react-router-dom 是React应用中用于路由的软件包,react-router-native 有用于开发React Native应用的绑定。实际上react-router-domreact-router的所有web应用相关导出,所以我们所有的东西都可以直接从react-router-dom中直接引用就可以了,这也是官方的推荐做法。

React Router的新特性

  1. <Switch>重命名为<Routes>
  2. <Route>的新特性变更,嵌套路由变得更简单。
  3. useNavigate代替useHistory
  4. 新钩子useRoutes代替react-router-config
  5. 大小减少:从20kb8kb
  6. 使用传参,路由参数使用方法。

<Switch>重命名为<Routes>

从用法上目前没有看出有多大区别,感觉就是换了个名字,这个新的元素是 Switch 组件的升级版,它包括相对路由和链接、自动路由排名、嵌套路由和布局等功能

//v5
<Switch> 
    <Route path="/" component={Home} /> 
</Switch> 
//v6
<Routes> 
    <Route path="/" element={<Home />} /> 
    //匹配未定义的路由地址
    <Route path={"*"} element={<div>暂无此页面</div>}/>
</Routes> 

<Route>的新特性变更,嵌套路由变得更简单。

1.component/renderelement替代,而且element只能传入一个React.ReactElement(组件)。

从这个图里我们可以看出,<Route>能用的参数只有4个,index已经被写死了,不可改变,其中element被限制只能上传组件。其余两个目前我这边还没用到(已经够用了其实,以后有时间再去了解下) 截屏2021-12-10 上午10.24.03.png

2.可以使用套娃模式进行多级路由嵌套的设定

截屏2021-12-10 上午11.12.13.png

使用<Outlet/>占位

决定子路由的渲染位置,这点是真的舒服,这样我们所有的所有路由都可以在一个App.tsx文件中维护起来,而其他页面只需要 <Outlet/>占个位置就可以方便的处理渲染位置的问题了,简直不要太爽。具体操作请看代码 ⇩⇩

多级路由嵌套的默认路由

如果不注意就会出现页面只渲染了一部分的情况,这种情况在用户手动改变地址栏时会出现。例如地址输入“/”,这时会发现页面只有Home页面内容出来了,而子路由的部分变空了,所以要设置默认路由,当地址输入不全时自动帮用户定位到完整的路由。
在子路由中定义<Route path="" element={<Navigate to={"地址"} />}/>path也可以设置为‘/父级路由地址’,具体操作请看代码 ⇩⇩

//App.tsx页面
    <Routes>
            <Route path={`/`} element={<Home />}>
              <Route path={`game`} element={<Game />}>
                <Route path={"info"} element={<GameInfo />} />
                <Route path={"man"} element={<GameMan />} />
                //默认路由,path也可以设置为‘/game’,地址为‘/game’时,重定向到"/game/info"
                <Route path="" element={<Navigate to={"/game/info"} />} />
              </Route>
              //默认路由,path也可以设置为‘/’,地址为‘/’时,重定向到"/game/info"
              <Route path="" element={<Navigate to={"/game/info"} />} />
            </Route>
            <Route path={`Index`} element={<Index/>}>
            <Route path={"*"} element={<div>暂无此页面</div>}/>
     </Routes>
     
 //Home.tsx页面
            <HomeHeader>
                <div className="headerNav">
                    <div className="server">
                        <div>tab1</div>
                        <div>tab2</div>
                        <div>tab3</div>
                        <div>tab4</div>
                    </div>
                </div>
            </HomeHeader>
            <HomeContent>
            //game会在此处(<Outlet/>所在位置)渲染
                <Outlet/>
            </HomeContent>

注意: <Route path="" element={<Navigate to={"/game/info"} />} /><Route path={"*"} element={<div>暂无此页面</div>}/> 是不一样的,path=“*”意味着在所有路径都不符合的情况下,而path=“”是父级路由匹配到了,子级路由地址没写时的情况下匹配的子级路由path=“*”只需要设置一个就好,而path=“”可能要设置很多次。

3. 用useNavigate代替useHistory

这个不知道该如何评价。。。对于用惯了类写法的同学来说,这看着是真难受。。。

截屏2021-12-10 上午11.24.42.png 现在,history.push()被替换为navigation(path,{replace:boolean,state:any})

// v5
import { useHistory } from 'react-router-dom';

function Index() {
  let history = useHistory();
  function handleClick() {
    history.push('/home');
  };
  return <button onClick={handleClick}>Submit</button>;
};

// v6
import { useNavigate } from 'react-router-dom';

function Index() {
  let navigate = useNavigate();
  function handleClick() {
    navigate('/home');
  };
  return <button onClick={handleClick}>Submit</button>;
};

history的用法也将被替换成:

// v5 
history.push('/index'); 
history.replace('/index'); 

// v6 
navigate('/index'); 
navigate('/index', {replace: true});

4.新钩子useRoutes代替react-router-config

看起来,简洁了一些,对hooks写法更友好了一些

function App() {
  let element = useRoutes([
    { path: '/', element: <Index /> },
    { path: 'dashboard', element: <Dashboard /> },
    { path: 'invoices',
      element: <Invoices />,
      children: [
        { path: ':id', element: <Invoice /> },
        { path: 'sent', element: <SentInvoices /> }
      ]
    },
    // 重定向
    { path: 'index', redirectTo: '/' },
    // 404找不到
    { path: '*', element: <NotFound /> }
  ]);
  return element;
}

5. 大小减少:从20kb8kb

这个点,没什么好说的了,v6版本相比以前的少了很多方法,和组件,更加精简了。包的体积也是少了一半多。

aHR0cHM6Ly90dmExLnNpbmFpbWcuY24vbGFyZ2UvMDA4MzFyU1RneTFnY3k1bmZjb212ajMxcGgwZjlnb2guanBn.jpeg

6. 使用路由传参,路由参数使用方法。

1./index/:id ⇨ useParams
2./index?name="xioaming"&age="18 ⇨ useSearchParams
3.通过路由state传参 ⇨ useLocation