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组件 用于显示子路由页面 \
- 用法/注意的地方
- 如果要实现嵌套路由的话,那么需要有一个Layout组件和Outlet组件,布局和显示。
- Layout组件,即布局组件。里面有Outlet组件用于显示子组件,可在里面放置侧边栏/路由链接等内容,自己编写。 = Outlet组件,router官方组件,相当于vue的router-view组件。嵌套的页面会挂载在Outlet组件上。
- 如果要依靠Outlet实现嵌套路由的话,那么可以实现所有路由都放在router.js,只需要在对应页面增加Outlet的方式。
- 如果有嵌套路由的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的方式来实现而已。
我们现在来改造一下上面的例子
注意:
- Route和Outlet其实是一个概念,可以当成同一个东西来使用,甚至在页面中同事引入这两个组件,会出现页面出现挂载在两个元素的情况
- 通过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;
总结
迁移方案其实也很简单,这边简单做个总结:
- 修改package.json中包的版本,记得删掉重新下载npm包。
- 修改Switch组件为Routes组件。
- router.config.js的修改,可以参考嵌套路由的两种方式,也可以参考useRouter的实现。
- 这边主要是写了一些Router组件方面的介绍,像是link组件,api等的介绍可以参考下面两篇文章