首页 > 解决方案 > 仅悬停时显示与菜单相关的元素

问题描述

在我的 React 项目中,我有一个包含 2 个主列表/导航项的菜单,并且希望在悬停时显示一个元素,并且当用户悬停在子菜单上时也保持可见。我可以使用 csshover和基于状态设置 className来完成这项工作boolean

问题是,当用户将鼠标悬停在子菜单上时,如何让与该菜单相关的元素显示?现在,当子菜单悬停时,这两个元素都会显示。我.map用来填充菜单和子菜单项,所以想知道是否有我传入的道具来控制它?

这是代码:

import React, { useState } from "react";
import styles from "./nav.module.scss";
import "../../styles/main.scss";

const Nav = ({
  navItems = [
    {
      id: "",
      label: "",
      subMenu: [{}]
    }
  ]
}) => {
  const [ballColor, setBallColor] = useState();
  const [showBall, setShowBall] = useState(false);

  const handleHover = () => {
    setShowBall(!showBall);
  };

  return (
    <>
      <nav>
        {/* Start of Menu Items */}
        <div className={styles.menuItemsContainer}>
          <ul className={styles.navUl}>
            {navItems.map(item => (
              <li key={item.id}>
                <a href="https://www.google.com">
                  <div
                    className={
                      showBall
                        ? `${styles.ball} ${styles.showBall} ${
                            styles[ballColor]
                          }`
                        : `${styles.ball} ${styles[ballColor]}`
                    }
                  />
                  {item.label}
                </a>
                <ul
                  className={
                    item.subMenu.length === 0
                      ? `${styles.noDisplay}`
                      : `${styles.display}`
                  }
                  onMouseEnter={handleHover}
                  onMouseLeave={handleHover}
                >
                  {item.subMenu.map(subItem => (
                    <li
                      key={subItem.id}
                      className={styles[subItem.class]}
                      onMouseOver={() => {
                        setBallColor(subItem.ballColor);
                      }}
                      onMouseLeave={() => setBallColor(null)}
                    >
                      {subItem.item}
                    </li>
                  ))}
                </ul>
              </li>
            ))}
          </ul>
        </div>
        {/* End of Menu Items */}
      </nav>
    </>
  );
};

export default Nav;

请参阅沙盒以供参考。

标签: javascriptreactjs

解决方案


你想要的是一组颜色:每个主菜单一个颜色。

以下代码是实现它的一种方法,我不喜欢循环中的所有这些循环,因此它只是向您展示如何处理它的一种方法,但可能不是最好的:

import React, { useState } from "react";
import styles from "./nav.module.scss";
import "../../styles/main.scss";

const Nav = ({
  navItems = [
    {
      id: "",
      label: "",
      subMenu: [{}]
    }
  ]
}) => {
  const [ballColors, setBallColor] = useState(["#fff", "#fff"]);
  const [showBalls, setShowBall] = useState([false, false]);

  const handleHover = i => {
    setShowBall([...showBalls].map((bool, j) => (i === j ? !bool : bool)));
  };

  return (
    <>
      <nav>
        {/* Start of Menu Items */}
        <div className={styles.menuItemsContainer}>
          <ul className={styles.navUl}>
            {navItems.map((item, i) => (
              <li key={item.id}>
                <a href="https://www.google.com">
                  <div
                    className={
                      showBalls[i]
                        ? `${styles.ball} ${styles.showBall} ${
                            styles[ballColors[i]]
                          }`
                        : `${styles.ball} ${styles[ballColors[i]]}`
                    }
                  />
                  {item.label}
                </a>
                <ul
                  className={
                    item.subMenu.length === 0
                      ? `${styles.noDisplay}`
                      : `${styles.display}`
                  }
                  onMouseEnter={() => handleHover(i)}
                  onMouseLeave={() => handleHover(i)}
                >
                  {item.subMenu.map((subItem, j) => (
                    <li
                      key={subItem.id}
                      className={styles[subItem.class]}
                      onMouseOver={() => {
                        setBallColor(
                          [...ballColors].map((color, k) =>
                            i === k ? subItem.ballColor : color
                          )
                        );
                      }}
                      onMouseLeave={() =>
                        setBallColor(
                          [...ballColors].map((color, k) =>
                            i === k ? "#fff" : color
                          ),
                          i
                        )
                      }
                    >
                      {subItem.item}
                    </li>
                  ))}
                </ul>
              </li>
            ))}
          </ul>
        </div>
        {/* End of Menu Items */}
      </nav>
      ballColors: {ballColors.join(" ")}
    </>
  );
};

export default Nav;

这是您的 codepen 的一个分支,作为该解决方案的演示。


推荐阅读