Router v6.x新特性以及旧项目迁移

1,411 阅读4分钟

Router v6.x新特性以及旧项目迁移

参考链接: blog.csdn.net/weixin_4090…

1. 更新语句
npm install react-router@6 react-router-dom@6
2. Switch 更改为Routes

这是最容易被看到的更改,Switch在6.x版本会使用会报找不到的错误,而迁移也很简单,使用Routes替换即可,其大部分的特性并没有被改变。

// v5
<Switch>
    <Route exact path="/"><Home /></Route>
    <Route path="/profile"><Profile /></Route>
</Switch>

// v6
<Routes>
    <Route path="/" element={<Home />} />
    <Route path="profile/*" element={<Profile />} />
</Routes>
3. Route的新特性变更

component/render被element替代

import Profile from './Profile';

// v5
<Route path=":userId" component={Profile} />
<Route
  path=":userId"
  render={routeProps => (
    <Profile routeProps={routeProps} animate={true} />
  )}
/>

// v6
<Route path=":userId" element={<Profile />} />
<Route path=":userId" element={<Profile animate={true} />} />
4. 嵌套路由的变更

具体变化有以下:

  • 已更改为接受子路由。
  • 比和更简单的匹配规则。
  • 路径层次更清晰 最直观的变更即是Redirect组件的废弃
    嵌套路由的实现方式
1. outlet实现 相当于vue的router-view组件 用于显示子路由页面 \
  • 用法/注意的地方
    1. 如果要实现嵌套路由的话,那么需要有一个Layout组件和Outlet组件,布局和显示。
    • Layout组件,即布局组件。里面有Outlet组件用于显示子组件,可在里面放置侧边栏/路由链接等内容,自己编写。 = Outlet组件,router官方组件,相当于vue的router-view组件。嵌套的页面会挂载在Outlet组件上。
    1. 如果要依靠Outlet实现嵌套路由的话,那么可以实现所有路由都放在router.js,只需要在对应页面增加Outlet的方式。
    2. 如果有嵌套路由的path需要加/* 实现方案:
      router.js
import { HashRouter as Router, Routes, Route } from "react-router-dom";
import LayoutIndex from "../layout";
import Home from "../pages/home/index";
import Test1 from "../pages/test1";

const RouterFun = () => {
  return (
    <Router>
      {/* 使用lazy异步加载组件后,需要配合使用Suspense组件包裹。fallback可以为loading,为异步包裹的内容 */}
      {/* 需要该组件路由才能显示 */}
      <Routes>
        <Route path="/*" element={<LayoutIndex />}>
          <Route path="index/*" element={<Home />}>
            <Route path="test1" element={<Test1 />} />
          </Route>
        </Route>
      </Routes>
    </Router>
  );
};

export default RouterFun;

LayoutIndex.tsx

import { Outlet } from "react-router-dom";
import Head from './head/index' //* 引入头部
import Footer from './footer/index' //* 引入底部

const LayoutIndex = () => {
  return (
    <div id="layout-index" className="layout-index common-width-100vw">
        <Head />
        <Outlet/>
        <Footer />
    </div>
  );
};

export default LayoutIndex;

Home.tsx

import { Outlet } from "react-router-dom";

const HomeIndex = () => {
    return (<div>
        <Outlet/>

        首页
    </div>);
}

export default HomeIndex;

Test.tsx

const Test = () => {
    return (<div>Test1
    </div>)
}
export default Test

上面例子在router.js中直接将嵌套路由给写了出来,然后只用保证页面有可以显示下级路由的Outlet即可。
即LayoutIndex中有显示Home组件的Outlet,Home组件中有显示Test1组件的Outlet

2. 下方页面嵌套Route显示

这种写过v5.x版本的朋友应该了解。即不使用Outlet,Route本身即是一个Layout。让我们改造一下上面的例子来实现 router.js

import { HashRouter as Router, Routes, Route } from "react-router-dom";
import LayoutIndex from "../layout";

const RouterFun = () => {
  return (
    <Router>
      {/* 使用lazy异步加载组件后,需要配合使用Suspense组件包裹。fallback可以为loading,为异步包裹的内容 */}
      {/* 需要该组件路由才能显示 */}
      <Routes>
        <Route path="/*" element={<LayoutIndex />}>
        </Route>
      </Routes>
    </Router>
  );
};

export default RouterFun;

LayoutIndex.tsx

import { Routes, Route } from "react-router-dom";
import Head from './head/index' //* 引入头部
import Footer from './footer/index' //* 引入底部
import Home from "../pages/home/index";

const LayoutIndex = () => {
  return (
    <div id="layout-index" className="layout-index common-width-100vw">
        <Head />
        <Routes>
          <Route path="index/*" element={<Home/>}></Route>
        </Routes>
        <Footer />
    </div>
  );
};

export default LayoutIndex;

Home.tsx

import { Routes, Route } from "react-router-dom";
import Test1 from "../test1";
const HomeIndex = () => {
    return (<div>
        <Routes>
          <Route path="test1" element={<Test1/>}></Route>
        </Routes>

        首页
    </div>);
}

export default HomeIndex;

test1.jsx

const Test = () => {
    return (<div>Test1
    </div>)
}
export default Test

这种方式无非就是将Outlet换成了Route来使用。但是我并不推荐这种方式,因为这种方式并不能将所有路由以一种路由树的方式展现。而useRoutes的出现代替了之前router.config.js的存在。
而如果在使用这种方式的话,可以尝试着使用一下Route的index设置为主路由,如果设置为主路由的话则不能有children

属性

如果我们在多级路由的情况,需要一个首页,或者默认页面。那么index属性将会帮到你。
让我们改造一下上面的例子。
Home.jsx

import { Routes, Route } from "react-router-dom";
import Test1 from "../test1";
import Test from '../test'
const HomeIndex = () => {
    return (<div>
        <Routes>
          <Route index element={<Test />}></Route> 
          <Route path="test1" element={<Test1/>}></Route>
        </Routes>

        首页
    </div>);
}

export default HomeIndex;

我们在Home页面里加了个默认路由,在我们刚进入这个页面时将会显示Test组件。

useRoutes

我们可以通过useRoutes的方式来生成一个路由树,其实这种方式类似于我们上面写的Outlet的方式。只是使用Hook的方式来实现而已。
我们现在来改造一下上面的例子
注意:

  1. Route和Outlet其实是一个概念,可以当成同一个东西来使用,甚至在页面中同事引入这两个组件,会出现页面出现挂载在两个元素的情况
  2. 通过useRoutes生成的element还是需要挂载在Router组件下 router.config.js
import { HashRouter as Router, Routes, Route, useRoutes } from "react-router-dom";
import LayoutIndex from "../layout";
import Home from "../pages/home";
import Test1 from '../pages/test1'

const RouterConfig = () => {
    const element = useRoutes([
        {
          path: "/",
          element: <LayoutIndex />,
          children: [
              {
                  path: 'index/*',
                  element: <Home />,
                  children: [
                      {
                          path: 'test1',
                          element: <Test1 />,
                      }
                  ]
              }
          ]
        },
      ]);
    return element
}

export default RouterConfig

router.js

import { HashRouter as Router } from "react-router-dom";
import RouterConfig from "./router.config";
const RouterFun = () => {

    
  return (
    <Router>
      <RouterConfig />
    </Router>
  );
};

export default RouterFun;

layout等组件和Outlet的引用一致
Home.tsx

import { Routes, Route, Outlet } from "react-router-dom";
import Test from '../test'
const HomeIndex = () => {
    return (<div>
        <Routes>
          <Route index element={<Test />}></Route> 
        </Routes>
        <Outlet />
        首页
    </div>);
}

export default HomeIndex;
总结

迁移方案其实也很简单,这边简单做个总结:

  1. 修改package.json中包的版本,记得删掉重新下载npm包。
  2. 修改Switch组件为Routes组件。
  3. router.config.js的修改,可以参考嵌套路由的两种方式,也可以参考useRouter的实现。
  4. 这边主要是写了一些Router组件方面的介绍,像是link组件,api等的介绍可以参考下面两篇文章
参考链接