Antd面包屑,超出宽度省略号

业务需求:面包屑超出宽度,左侧出现省略号。

实现效果

Antd面包屑,超出宽度省略号_第1张图片

实现原理

  1. 先调整面包屑样式,使其弹性布局不换行
  2. 给面包屑外面盒子一个ref,面包屑同级有个隐藏的span,内容是…省略号
  3. 通过MutationObserver监听这个盒子的内容改变
  4. 当内容超出盒子宽度之后,打开省略号,并修改弹性布局主轴从行尾开始

核心代码

MutationObserver对象监听dom元素内容
MutationObserver

代码

import { useEffect, useRef, useState } from "react";
import { Breadcrumb } from "antd";
import "antd/lib/breadcrumb/style/css";
import "./index.css";
function Index(props: any) {
  const [breadcrumb, setBreadcrumb] = useState([
    {
      title: "Home",
      href: "1",
    },
    {
      title: "Page1",
      href: "1",
    },
    {
      title: "Page2",
      href: "1",
    },
  ]);
  const [showEllipsis, setShowEllipsis] = useState(false);
  const breadCrumbsRef = useRef<any>();

  // 观察面包屑dom实现省略号
  useEffect(() => {
    const targetNode = breadCrumbsRef?.current;
    const config = { attributes: false, childList: true, subtree: true };
    const callback = function (mutationsList: any, observer: any) {
      for (let mutation of mutationsList) {
        if (mutation.type === "childList") {
          let childWidth = 0;
          for (const childNodes of mutation.target.childNodes) {
            childWidth += childNodes.clientWidth;
          }
          if (mutation.target.clientWidth < childWidth) {
            mutation.target.style.justifyContent = "flex-end";
            setShowEllipsis(true);
          } else if (mutation.target.clientWidth >= childWidth) {
            mutation.target.style.justifyContent = "flex-start";
            setShowEllipsis(false);
          }
        }
      }
    };
    // 创建一个观察器实例并传入回调函数
    const observer = new MutationObserver(callback);
    // 以上述配置开始观察目标节点
    observer.observe(targetNode, config);
    return () => {
      // 停止观察
      observer.disconnect();
    };
  }, []);

  const onClickIncrease = () => {
    breadcrumb.push({
      title: `Page${
        parseInt(breadcrumb[breadcrumb.length - 1].title.slice(4)) + 1
      }`,
      href: "",
    });
    setBreadcrumb([...breadcrumb]);
  };

  const onClickDecrease = () => {
    breadcrumb.pop();
    setBreadcrumb([...breadcrumb]);
  };

  return (
    <div className="breadcrumb-wrapper" ref={breadCrumbsRef}>
      <span
        className={`breadcrumb-ellipsis ${
          showEllipsis ? "breadcrumb-ellipsis-show" : ""
        }`}
      >
        ....
      </span>
      <Breadcrumb>
        {breadcrumb.map((item, index) => {
          return <Breadcrumb.Item key={index}>{item.title}</Breadcrumb.Item>;
        })}
      </Breadcrumb>
      <button onClick={onClickIncrease}>+++</button>
      <button onClick={onClickDecrease}>---</button>
    </div>
  );
}

export default Index;
.breadcrumb-wrapper {
  position: relative;
  margin: 50px;
  width: 300px;
  height: 200px;
  border: 1px #ccc solid;
}
.breadcrumb-ellipsis {
  position: absolute;
  left: 0;
  top: 0;
  background: #fff;
  visibility: hidden;
  font-size: 12px;
}
.breadcrumb-ellipsis-show{
  visibility: initial;
}
.ant-breadcrumb > ol {
  display: flex;
  flex-wrap: nowrap;
  overflow: hidden;
}

其他拓展

相对应的,既然有了省略号了,业务需求想直接跳到首页,总不能一级一级往回点吧。与之相对应UI的设计思路是,鼠标悬浮,有个tooltip,里面存放全部的面包屑路径。这种情况就用andt的tooltip包起来,技术上亲测是可行的。

感谢观看!

你可能感兴趣的:(React技术栈相关,JS,Ant,Design,前端,javascript,react.js,antd)