如何为支持自定义节点的React Breadcrumb面包屑组件添加路由跳转功能
完全可以实现,你只需要调整面包屑的数据结构搭配react-router的路由跳转API即可,以下是具体实现方案:
实现思路
- 将原面包屑字符串数组改为带
label(显示文本)和path(对应路由路径)的对象数组,适配任意数量的自定义节点 - 在父组件中引入react-router的路由跳转API,点击节点时跳转对应路径
- 保证每个crumb的
path和你路由配置中Route的path属性完全匹配即可
修改后的代码
父组件(以react-router v5为例,适配你给出的Switch写法)
import React, { useState } from 'react'; import { useHistory } from 'react-router-dom'; import Breadcrumbs from './Breadcrumbs'; export interface BreadcrumbProps {} export function Breadcrumb(props: BreadcrumbProps) { const history = useHistory(); // 自定义任意数量的节点,每个节点对应路由path const [crumbs, setCrumbs] = useState([ { label: 'Home', path: '/' }, { label: 'Category', path: '/component0' }, { label: 'Sub Category', path: '/component1' } // 后续可随意新增节点,只要对应上Route配置的path即可 ]); const selected = (crumb: {label: string, path: string}) => { // 跳转对应路由,同步修改页面URL history.push(crumb.path); }; return ( <div> <Breadcrumbs crumbs={crumbs} selected={selected} /> </div> ); } export default Breadcrumb;
子组件(仅需调整取值逻辑,兼容任意数量节点)
interface CrumbItem { label: string; path: string; } interface BreadcrumbsProps { crumbs: CrumbItem[]; selected: (crumb: CrumbItem) => void; } function Breadcrumbs(props: BreadcrumbsProps) { function isLast(index: number) { return index === props.crumbs.length - 1; } return ( <nav className=''> <ol className=''> {props.crumbs.map((crumb, ci) => { const disabled = isLast(ci) ? 'disabled' : ''; return ( <li key={ci} className=''> <button className={`btn btn-link ${disabled}`} onClick={() => props.selected(crumb)}> {crumb.label} </button> </li> ); })} </ol> </nav> ); } export default Breadcrumbs;
react-router v6适配方案
如果你用的是react-router v6,仅需修改父组件的跳转逻辑即可:
// 替换useHistory为useNavigate import { useNavigate } from 'react-router-dom'; // 组件内替换history相关代码 const navigate = useNavigate(); const selected = (crumb: {label: string, path: string}) => { navigate(crumb.path); };
嵌套路由场景适配(可选)
如果你的路由是多级嵌套格式(比如/a/b/c),还可以不用手动写全每个节点的path,在子组件map时自动拼接路径,进一步简化配置,不管加多少级节点都能自动生成对应路由:
// 子组件map部分修改为 {props.crumbs.map((crumb, ci) => { const disabled = isLast(ci) ? 'disabled' : ''; // 自动拼接前ci+1级的路径 const fullPath = `/${props.crumbs.slice(0, ci+1).map(item => item.path).join('/')}` return ( <li key={ci} className=''> <button className={`btn btn-link ${disabled}`} onClick={() => props.selected({...crumb, path: fullPath})}> {crumb.label} </button> </li> ); })}
内容的提问来源于stack exchange,提问作者Leo Messi
相关产品推荐
相关产品推荐

