嵌套路由路径

如果路由路径嵌套深了,并且是写死的,如果有一天想改变一个路径,那不就GG了??
所以,子组件的路由路径前缀应该拿到父组件的path才行!

解决方案

重点在于React没有限制我们,所以,只要我们有办法解决即可!

  1. match中的url是:真实路径中匹配到路径规则的字符串
    1. 子组件path的前缀是父组件的match.url即可
  2. 将所有路由配置抽离出来放到RouteConfig.js,再利用辅助方法导出即可

image.png
image.png

受保护的页面

image.png
公共的授权信息,学了Redux就用Redux处理,目前没学。我们可以直接放在一个对象中

补充: Route组件的render属性

render和children的区别:render是匹配之后才会运行,children无论是否匹配都会运行

  1. <Route path='personal' rende={(values) => {//values是上下文对象,包含history,location,match,staticContext
  2. return 一个类型为React.ReactNode的东西即可
  3. }} />

自定义路由—组件

根据不同的地址,显示不同的组件
所以利用上述玩法,可以实现一个通用的组件,判断如何跳转

ProtectedRoute.js组件
image.png
image.png
如何从授权页跳回之前的页面呢?
方法一:老方法,利用search的参数returnurl,这样会在地址栏中显示
方法二:新方法,location(hash模式也可以带state)中的state附带returnurl,这样就不会再地址栏中显示了
image.png

【扩展】实现Vue路由模式

  1. //RootRouter.js
  2. import React from "react";
  3. import { Route, Switch } from "react-router";
  4. /**
  5. * 根据一个路由配置数组,遍历该数组,得到一组Route组件
  6. */
  7. export function getRoutes(routes, basePath) {
  8. if (!Array.isArray(routes)) {
  9. return null;
  10. }
  11. const rs = routes.map((rt, i) => {
  12. const { name, children, path, component: Component, ...rest } = rt;
  13. let newPath = `${basePath}${path}`;
  14. newPath.replace(/\/\/+/g, "/");
  15. return (
  16. <Route
  17. key={i}
  18. {...rest}
  19. render={(values) => {
  20. return (
  21. <Component {...values}>{getRoutes(rt.children, newPath)}</Component>
  22. );
  23. }}
  24. />
  25. );
  26. });
  27. return <Switch>{rs}</Switch>;
  28. }
  29. //使用Route组件,根据不同的路径,渲染顶级页面
  30. export default function RootRouter() {
  31. return <>{getRoutes(routeConfig)}</>;
  32. }
  1. //BetterLink.js
  2. import React from "react";
  3. import { Link } from "react-router-dom";
  4. export default function BetterLink(props) {
  5. const { to, ...rest } = props;
  6. if (to.name && typeof to !== "string") {
  7. to.pathname = getPathFromName(to.name, '/', routeConfig);
  8. if(to.pathname === undefined){
  9. throw new Error(`name属性值${to.name}无效!`)
  10. }
  11. }
  12. return <Link {...rest} to={to} />
  13. }
  14. /**
  15. 根据name的值,查找对应的path,没有考虑有params的情况
  16. 如果有,会比较复杂,需要用到path-to-regexp库
  17. */
  18. function getPathFromName(name, baseUrl, routesArr) {
  19. for (const item of routesArr) {
  20. let newPath = `${baseUrl}${item.path}`;
  21. newPath.replace(/\/\/+/g, "/");
  22. if (item.name === name) {
  23. return baseUrl + item.path;
  24. } else {
  25. if (Array.isArray(item.children)) {
  26. const path = getPathFromName(name, newPath, item.children);
  27. if (path !== undefined) {
  28. return path;
  29. }
  30. }
  31. }
  32. }
  33. }

实现导航守卫

路由切换动画

滚动条复位

阻止跳转