如何在React中最好地实现多行面包屑链接?

9

我正在尝试为移动/平板设备实现多行面包屑链接。用户将浏览多个文件夹,如果超过了面包屑链接容器配置的最大行数,我将从开头删除链接(尝试显示当前路径的最大路径)。找不到这种情况的CSS方法。请参见下面的示例,其中max line = 2

current path = 
path1 / path2 
/ path3 / path4
/path5

在path5处超过了限制(跳到第3行),应该更新链接

updated path = 
.../ path2 
/ path3 / path4

如果用户回退,应该更新而不使用省略号。我尝试了以下方法,但效果并不如预期 -

  1. 使用 CSS 的 clamp 方法来限制最大行数 // 这种方法行不通,因为我们需要找到要修剪多少个链接
  2. 使用 white-space: no wraptext-overflow: ellipse,但无法使用它,因为它不允许多行
  3. 使用表达式尝试找出单个 div 行中最多适合的字符数 - Width(in pixel) * Font Constant / font Size (in pixels)

已经动态确定了宽度和字体大小,但无法确定元素的字体常数。非常感谢任何帮助。


你可以使用一些JS来计算容器的高度(即路径所在的元素),并将每个路径包装在单独的元素中(<span>path1</span>,...),然后从开头删除尽可能多的<span />元素,直到容器达到其最大高度。 - Fatorice
那我需要使用纯JavaScript对吧?有没有其他方法可以使用组件完成呢? - Naveen
3个回答

1
我在这里创建了一个演示组件,希望它能有所帮助。
我使用的策略是:
  1. 通过将包装器的高度除以行高来计算行数
  2. 从开头删除项目,直到行数减少到允许的最大值

Breadcrumbs.js

import { createRef, useEffect, useState } from "react";
import "./Breadcrumbs.css";

function Breadcrumbs() {

    const wrapper = createRef();
    const ellipsis = createRef();
    const [items, setItems] = useState([]);
    const [dropped, setDropped] = useState(false);

    const countLines = (element, lineHeight) => {
        let height = element.offsetHeight;
        let lines = height / lineHeight;
        return Math.round(lines);
    }

    useEffect(() => {
        setItems(window.location.pathname.split("/").filter((e) => e.length > 0))
    }, [window.location.pathname])

    useEffect(() => {
        const lines = countLines(wrapper.current, ellipsis.current.clientHeight);
        const maxLines = 2;

        if (lines > maxLines) {
            setItems(items.slice(1));
            setDropped(true);
        }
    }, [items])

    return <nav className="breadcrumbs-wrapper" ref={wrapper}>
        <span ref={ellipsis}>
            {dropped ? "..." : ""}
        </span>
        {items.map((item, index) => {
            return <span key={index.toString()}>
                <span>&nbsp;/&nbsp;</span>
                <a href="#">{item}</a>
            </span>
        })}
    </nav>
}

export default Breadcrumbs;

Breadcrumbs.css

.breadcrumbs-wrapper {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}

以下是工作示例的屏幕截图:

没有换行的一行

两行

超过两行


如果路径的长度像“这是一个路径示例”会发生什么? - Naveen

0

import React from 'react'; { Link, useLocation } from 'react-router-dom';

从'react'导入React; 从'react-router-dom'导入Link和useLocation;

const Breadcrumb = ({ handleDrawerOpen, open }) => {
   const { pathname } = useLocation();

   const pathName = (paths, index) => {
      return paths.filter((path, pathIndex) => pathIndex !== 0 && pathIndex <= index).join('/');
   };
   
   const func = () => {
      const paths = pathname.split('/');
      return paths.map(
         (path, index) =>
            index !== 0 && (
               <Link
                  style={{
                     textDecoration: 'none',
                     color: index === paths.length - 1 ? '#49C5B6' : 'white',
                  }}
                  to={`/${pathName(paths, index)}`}>{`${
                  path?.charAt(0)?.toUpperCase() + path.slice(1).toLowerCase()
               } ${index !== paths.length - 1 ? '>' : ''} `}</Link>
            )
      );
   };
   return (
      <Box>
         {!open && (
            <IconButton onClick={handleDrawerOpen}>
               <MenuIcon />
            </IconButton>
         )}

         <Profile />
      </Box>
   );
};

export default Breadcrumb;

0

您可以切片最后5个项目并通过它们进行映射以呈现链接:

breadcrumbs.slice(-5).map((breadcrumb, index) => (
<React.Fragment key={index}>
  {index !== 0 && breadcrumbs.length > 1 ? ' / ' : ''}
  {index === 0 && breadcrumb.path !== breadcrumbs[0].path ? (
    '...'
  ) : (
    <a href={breadcrumb.link}>{breadcrumb.path}</a>
  )}
  {index % 2 ? <br /> : ''}
</React.Fragment>

这里有一个演示,符合您的要求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接