道招

React router用hooks读取routeName、根据routeName跳转

如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!

React router用hooks读取routeName、根据routeName跳转

在迁移Vue至React的过程中遇到了一些路由相关的问题,在Vue项目中经常会使用routeName,毕竟使用path太长了,也记不住,我自己看了看React router也没有发现routeName相关的信息,可能是我没有找到,或者React没有这个概念吧。

在Vue中这样的写法比较常见

const router = new Router({
  routes: [{
      path: '/smart-mail',
      name: 'SmartMailBox',
      redirect: '/smart-mail/no-mail',
      component: SmartMailBox,
      children: [{
          path: 'new/:ts',
          name: 'MailNew',
          component: smartMailNew,
        },
        {
          path: 'info',
          name: 'MailDetail',
          component: smartMailInfo,
          children: [{
              path: 'view/:uid/:ts',
              name: 'MailView',
              component: smartMailView,
            },
            {
              path: 'reply/:uid/:ts',
              name: 'MailReply',
              component: smartMailReply,
            },
            {
              path: 'reply-all/:uid/:ts',
              name: 'MailReplyAll',
              component: smartMailReply,
            },
            {
              path: 'forward/:uid/:ts',
              name: 'MailForward',
              component: smartMailReply,
            },
            {
              path: 'draft/:uid/:ts',
              name: 'ReplyOrForwardDraft',
              component: smartMailReply,
            },
            {
              path: 'empty/:uid/:ts',
              name: 'MailEmpty',
              component: smartMailEmpty,
            },
            {
              path: 'new-draft/:uid/:ts',
              name: 'MailDraft',
              component: smartMailNew,
            },
          ],
        },
      ],
    },
  ],
});

需要跳转就使用routeName,避免长长的path

this.$router.push({
    name: 'MailView',
    params: {
       uid:  'xxx',
    }
})

file 迁移到React时可以这样做

// routes.js
export default [
  {
    path: "/smart-mail/no-mail",
    component: NoMail
  },
  {
    path: "/smart-mail/new/:ts",
    component: MailNew,
    routeName: 'MailNew'
  },
  {
    path: "/smart-mail/info/:uid",
    component: MailDetail,
    routes: [
      {
        path: "/smart-mail/info/view/:uid/:ts/:keyword?",
        component: MailView,
        routeName: 'MailView',
        exact: false,
      },
      {
        path: "/smart-mail/info/reply/:uid/:ts",
        component: MailReply,
        routeName: 'MailReply',
      },
      {
        path: "/smart-mail/info/replyAll/:uid/:ts",
        component: MailReply,
        routeName: 'MailReplyAll',

      },
      {
        path: "/smart-mail/info/forward/:uid/:ts",
        component: MailReply,
        routeName: 'MailForward',

      },
      {
        path: "/smart-mail/info/draft/:uid/:ts",
        component: MailReply,
        routeName: 'ReplyOrForwardDraft',

      },
      {
        path: "/smart-mail/info/empty/:uid/:ts",
        component: MailEmpty,
        routeName: 'MailEmpty',

      },
      {
        path: "/smart-mail/info/new-draft/:uid/:ts",
        component: MailNew,
        routeName: 'MailDraft',
      },
    ]
  },
];

上面的routeName是我们为了自己使用而额外增加的字段,我们可以自己写hook来实现根据routeName跳转了

// hook.js
import React from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import routes from "../../routes";

export function useReactRouter() {
  function findRoute(routes, routeName) {
    for (let item of routes) {
      if (item.routeName === routeName) {
        return item;
      } else if (item.routes){
        const result = findRoute(item.routes, routeName);
        if (result) {
          return result;
        }
      }
    }
  }

  function findRouteName(routes, pathName) {
    for (let item of routes) {
      if (item.routes) {
        return findRouteName(item.routes, pathName);
      } else {
        const staticPath = item.path.replace(/\/:\w+\??/g, '');
        const isMatch = pathName.indexOf(staticPath) === 0; // 判断是否当前pathName前部分是否与路由的静态地址前部分匹配
        if (isMatch) {
          return item.routeName;
        }
      }
    }
  }

  const history = useHistory();

  function historyPush(routeName, mailId, keyword = '') {
    const route = findRoute(routes, routeName);
    if (route) {
      const path = route.path.replace(':uid', mailId).replace(':ts', Date.now()).replace(':keyword', keyword);
      history.push(path);
    } else {
      throw new Error(`${routeName} not found`)
    }
  }
  const location = useLocation();

  const routeName = useMemo(() => {
    return findRouteName(routes, location.pathname);
  }, [location, routes]);

  return [routeName, historyPush, history];
}
获取routeName
  const [routeName] = useReactRouter();

根据当前路由的pathname在自己的静态路由表里面进行匹配,在匹配过程中有部分是动态参数,所以我们在定义路由的时候尽量将path里面的静态部分写在前面,方便匹配,需要注意前面匹配值的唯一性。

根据routeName跳转
  const [routeName, historyPush] = useReactRouter();
  historyPush.push('MailView', 'xxx');

这个有点类似上面过程的逆过程--根据routeName找到path,然后将传递的参数替换掉动态参数部分。

这样我们就可以类似Vue的方式来进行路由跳转了。

更新时间:
上一篇:邮箱收件人组件成长历程(三)跨栏拖拽不同数据方案对比下一篇:怎么调试Webpack+React项目,报错basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")怎么办

相关文章

vue-cli设置css不生效

我们有的项目使用的是老的vue-cli脚手架生成的,今天想写点东西,发现.vue文件里面 style 里面写的样式都不生效了,很自然就想到是不是loader的问题。 在这种项目的webpack.ba 阅读更多…

使用next.js服务端渲染经历

上周末的时候打算把自己的网站从vue的ssr转换为react的ssr,鉴于之前在vue中是用的原生的ssr,这次想在react中试试框架,所以首选的就是next.js。 第一次用next.js,根据 阅读更多…

用在线IDE写vue代码

上周末无意中发现了一个新的在线IDE,网址glitch.com,个人感觉很不错,于是顺便关注了下其它的在线IDE,比如codesandbox.io也不错,没有细看,可能自己已经先入为主的喜欢上glit 阅读更多…

vue多语言的解决方案不只是 vue-i18n,前端+后端完整解决方案

网上搜很多vue多语言的,一般都是介绍vue-i18n怎么使用,当然这是不错的,但是我们如果只是讲这个的话,只是解决了静态文字的多语言化。 这一部分我们也简单讲一下 npm install 阅读更多…

element-ui表单源码解析之el-input

关于表单校验el-input做的主要工作就是跟el-form-item交互,把input的相关事件发送给el-form-item,上一篇已经讲到在el-form-item的mounted的生命周期里 阅读更多…

怎么调试Webpack+React项目,报错basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")怎么办

今天在WebStorm上Windows上准备调试一个React项目,就出现了这样的报错。 Node Parameters里面写的是webpack-dev-server的执行文件 .\node_mod 阅读更多…

关注道招网公众帐号
友情链接
消息推送
道招网关注互联网,分享IT资讯,前沿科技、编程技术,是否允许文章更新后推送通知消息。
允许
不用了