广告
返回顶部
首页 > 资讯 > 精选 >如何利用React高阶组件实现一个面包屑导航
  • 267
分享到

如何利用React高阶组件实现一个面包屑导航

2023-06-05 03:06:19 267人浏览 八月长安
摘要

本篇内容介绍了“如何利用React高阶组件实现一个面包屑导航”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是 react 高阶组件rea

本篇内容介绍了“如何利用React高阶组件实现一个面包屑导航”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

什么是 react 高阶组件

react 高阶组件就是以高阶函数的方式包裹需要修饰的 react 组件,并返回处理完成后的 react 组件。react 高阶组件在 react 生态中使用的非常频繁,比如react-router 中的 withrouter 以及 react-redux 中 connect 等许多 api 都是以这样的方式来实现的。

使用 react 高阶组件的好处

在工作中,我们经常会有很多功能相似,组件代码重复的页面需求,通常我们可以通过完全复制一遍代码的方式实现功能,但是这样页面的维护可维护性就会变得极差,需要对每一个页面里的相同组件去做更改。因此,我们可以将其中共同的部分,比如接受相同的查询操作结果、组件外同一的标签包裹等抽离出来,做一个单独的函数,并传入不同的业务组件作为子组件参数,而这个函数不会修改子组件,只是通过组合的方式将子组件包装在容器组件中,是一个无副作用的纯函数,从而我们能够在不改变这些组件逻辑的情况下将这部分代码解耦,提升代码可维护性。

自己动手实现一个高阶组件

前端项目里,带链接指向的面包屑导航十分常用,但由于面包屑导航需要手动维护一个所有目录路径与目录名映射的数组,而这里所有的数据我们都能从 react-router 的路由表中取得,因此我们可以从这里入手,实现一个面包屑导航的高阶组件。

首先我们看看我们的路由表提供的数据以及目标面包屑组件所需要的数据:

// 这里展示的是 react-router4 的route示例let routes = [ {  breadcrumb: '一级目录',  path: '/a',  component: require('../a/index.js').default,  items: [   {    breadcrumb: '二级目录',    path: '/a/b',    component: require('../a/b/index.js').default,    items: [     {      breadcrumb: '三级目录1',      path: '/a/b/c1',      component: require('../a/b/c1/index.js').default,      exact: true,     },     {      breadcrumb: '三级目录2',      path: '/a/b/c2',      component: require('../a/b/c2/index.js').default,      exact: true,     },   }  ] }]// 理想中的面包屑组件// 展示格式为 a / b / c1 并都附上链接const breadcrumbscomponent = ({ breadcrumbs }) => ( <div>  {breadcrumbs.map((breadcrumb, index) => (   <span key={breadcrumb.props.path}>    <link to={breadcrumb.props.path}>{breadcrumb}</link>    {index < breadcrumbs.length - 1 && <i> / </i>}   </span>  ))} </div>);

这里我们可以看到,面包屑组件需要提供的数据一共有三种,一种是当前页面的路径,一种是面包屑所带的文字,一种是该面包屑的导航链接指向。

其中第一种我们可以通过 react-router 提供的 withrouter 高阶组件包裹,可使子组件获取到当前页面的 location 属性,从而获取页面路径。

后两种需要我们对 routes 进行操作,首先将 routes 提供的数据扁平化成面包屑导航需要的格式,我们可以使用一个函数来实现它。

const flattenroutes = arr => arr.reduce(function(prev, item) {  prev.push(item);  return prev.concat(   array.isarray(item.items) ? flattenroutes(item.items) : item  ); }, []);

之后将展平的目录路径映射与当前页面路径一同放入处理函数,生成面包屑导航结构。

export const getbreadcrumbs = ({ flattenroutes, location }) => { // 初始化匹配数组match let matches = []; location.pathname  // 取得路径名,然后将路径分割成每一路由部分.  .split('?')[0]  .split('/')  // 对每一部分执行一次调用`getbreadcrumb()`的reduce.  .reduce((prev, cursection) => {   // 将最后一个路由部分与当前部分合并,比如当路径为 `/x/xx/xxx` 时,pathsection分别检查 `/x` `/x/xx` `/x/xx/xxx` 的匹配,并分别生成面包屑   const pathsection = `${prev}/${cursection}`;   const breadcrumb = getbreadcrumb({    flattenroutes,    cursection,    pathsection,   });   // 将面包屑导入到matches数组中   matches.push(breadcrumb);   // 传递给下一次reduce的路径部分   return pathsection;  }); return matches;};

然后对于每一个面包屑路径部分,生成目录名称并附上指向对应路由位置的链接属性。

const getbreadcrumb = ({ flattenroutes, cursection, pathsection }) => { const matchroute = flattenroutes.find(ele => {  const { breadcrumb, path } = ele;  if (!breadcrumb || !path) {   throw new error(    'router中的每一个route必须包含 `path` 以及 `breadcrumb` 属性'   );  }  // 查找是否有匹配  // exact 为 react router4 的属性,用于精确匹配路由  return matchpath(pathsection, { path, exact: true }); }); // 返回breadcrumb的值,没有就返回原匹配子路径名 if (matchroute) {  return render({   content: matchroute.breadcrumb || cursection,   path: matchroute.path,  }); } // 对于routes表中不存在的路径 // 根目录默认名称为首页. return render({  content: pathsection === '/' ? '首页' : cursection,  path: pathsection, });};

之后由 render 函数生成最后的单个面包屑导航样式。单个面包屑组件需要为 render 函数提供该面包屑指向的路径 path, 以及该面包屑内容映射content 这两个 props。

const render = ({ content, path }) => { const componentprops = { path }; if (typeof content === 'function') {  return <content {...componentprops} />; } return <span {...componentprops}>{content}</span>;};

有了这些功能函数,我们就能实现一个能为包裹组件传入当前所在路径以及路由属性的 react 高阶组件了。传入一个组件,返回一个新的相同的组件结构,这样便不会对组件外的任何功能与操作造成破坏。

const breadcrumbshoc = ( location = window.location, routes = []) => component => { const breadcomponent = (  <component   breadcrumbs={getbreadcrumbs({    flattenroutes: flattenroutes(routes),    location,   })}  /> ); return breadcomponent;};export default breadcrumbshoc;

调用这个高阶组件的方法也非常简单,只需要传入当前所在路径以及整个 react router 生成的 routes 属性即可。
至于如何取得当前所在路径,我们可以利用 react router 提供的 withrouter 函数,如何使用请自行查阅相关文档。
值得一提的是,withrouter 本身就是一个高阶组件,能为包裹组件提供包括 location 属性在内的若干路由属性。所以这个 api 也能作为学习高阶组件一个很好的参考。

withrouter(({ location }) => breadcrumbshoc(location, routes)(breadcrumbscomponent));

q&a

如果react router 生成的 routes 不是由自己手动维护的,甚至都没有存在本地,而是通过请求拉取到的,存储在 redux 里,通过 react-redux 提供的 connect 高阶函数包裹时,路由发生变化时并不会导致该面包屑组件更新。使用方法如下:

function mapstatetoprops(state) { return {  routes: state.routes, };}connect(mapstatetoprops)( withrouter(({ location }) =>  breadcrumbshoc(location, routes)(breadcrumbscomponent) ));

这其实是 connect 函数的一个bug。因为 react-redux 的 connect 高阶组件会为传入的参数组件实现 shouldcomponentupdate 这个钩子函数,导致只有 prop 发生变化时才触发更新相关的生命周期函数(含 render),而很显然,我们的 location 对象并没有作为 prop 传入该参数组件。

官方推荐的做法是使用 withrouter 来包裹 connect 的 return value,即

withrouter( connect(mapstatetoprops)(({ location, routes }) =>  breadcrumbshoc(location, routes)(breadcrumbscomponent) ));

“如何利用React高阶组件实现一个面包屑导航”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

--结束END--

本文标题: 如何利用React高阶组件实现一个面包屑导航

本文链接: https://www.lsjlt.com/news/240830.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何利用React高阶组件实现一个面包屑导航
    本篇内容介绍了“如何利用React高阶组件实现一个面包屑导航”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是 react 高阶组件rea...
    99+
    2023-06-05
  • React高阶组件如何创建一个面包屑导航
    这篇文章主要介绍“React高阶组件如何创建一个面包屑导航”,在日常操作中,相信很多人在React高阶组件如何创建一个面包屑导航问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”React高阶组件如何创建一个面包...
    99+
    2023-07-04
  • css如何使用伪元素:before实现的面包屑导航栏
    小编给大家分享一下css如何使用伪元素:before实现的面包屑导航栏,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!伪元素:be...
    99+
    2022-10-19
  • vue3中使用ant-design-vue的layout组件实现动态导航栏和面包屑功能
    目录0 前言1 准备工作1.1 安装ant-design-vue1.2 安装图标组件包2 选择组件3 路由文件4 Vue导航页面5 最终效果0 前言   &nbs...
    99+
    2023-01-29
    vue3使用ant-design-vue实现动态导航栏 vue3使用ant-design-vue
  • 如何使用react实现一个tab组件
    这篇“如何使用react实现一个tab组件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“如何使用react实现一个tab组件...
    99+
    2023-07-04
  • React如何使用高阶组件与Hooks实现权限拦截
    本篇内容主要讲解“React如何使用高阶组件与Hooks实现权限拦截”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“React如何使用高阶组件与Hooks实现权限拦截”吧!高阶组件是以组件作为参数...
    99+
    2023-07-05
  • 如何使用React Portals实现一个功能强大的抽屉组件
    本篇内容介绍了“如何使用React Portals实现一个功能强大的抽屉组件”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读...
    99+
    2022-10-19
  • 如何利用Android组件实现一个列表选择框功能
    如何利用Android组件实现一个列表选择框功能?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。android提供的列表选择框(Spinner)相当于web端用户...
    99+
    2023-05-31
    android roi
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作