将鼠标悬停在显示菜单上

时间:2020-01-03 07:44:17

标签: javascript css reactjs twitter-bootstrap reactstrap

在React应用程序中,我正在使用reactstrap css框架制作下拉列表以列出下拉菜单。

示例。Js

      <Dropdown
        className="d-inline-block"
        onMouseOver={this.onMouseEnter}
        onMouseLeave={this.onMouseLeave}
        isOpen={this.state.dropdownOpen}
        toggle={this.toggle}
      >
        <DropdownToggle caret>Dropdown1</DropdownToggle>
        <DropdownMenu>
          <DropdownItem header>Submenu 1</DropdownItem>
          <DropdownItem>Submenu 1.1</DropdownItem>
        </DropdownMenu>
        &nbsp;&nbsp;&nbsp;
        <DropdownToggle caret>Dropdown2</DropdownToggle>
        <DropdownMenu>
          <DropdownItem header>Submenu 2</DropdownItem>
          <DropdownItem>Submenu 2.1</DropdownItem>
          <DropdownItem>Submenu 2.2</DropdownItem>
        </DropdownMenu>
        &nbsp;&nbsp;&nbsp;
        <br /><br />
        <DropdownToggle caret>Dropdown3</DropdownToggle>
        <DropdownMenu>
          <DropdownItem header>Submenu 3</DropdownItem>
          <DropdownItem>Submenu 3.1</DropdownItem>
          <DropdownItem>Submenu 3.2</DropdownItem>
          <DropdownItem>Submenu 3.3</DropdownItem>
        </DropdownMenu>
      </Dropdown>

在这里,我已经setState设置了dropDownOpenonMouseOver等事件中onMouseLeave的状态。

问题位于单个下拉菜单上,每个下拉菜单都被打开。

Click here for Working Demo

请帮助我将鼠标悬停在下拉菜单中,以便一次仅列出一个悬停的菜单,而并非全部

注意:在我的实际应用中,这些下拉菜单将是动态的,因此我无法设置任何硬编码状态,例如dropDown1dropDown2dropDown3 ...等等。

它可能有n个下拉菜单。.因此,请在考虑动态菜单的情况下为我提供解决方案。

5 个答案:

答案 0 :(得分:1)

基本上,每个下拉菜单都必须位于其自己的Dropdown复合组件中,并具有其自己的状态和处理程序。我分叉并更新了您的演示,希望能为您提供正确的想法。

<div>
    <Dropdown
      className="d-inline-block"
      onMouseOver={this.onMouseEnter}
      onMouseLeave={this.onMouseLeave}
      isOpen={this.state.dropdownOpen1}
      toggle={this.toggle1}
    >
      <DropdownToggle caret>Dropdown1</DropdownToggle>
      <DropdownMenu>
        <DropdownItem header>Submenu 1</DropdownItem>
        <DropdownItem>Submenu 1.1</DropdownItem>
      </DropdownMenu>
      &nbsp;&nbsp;&nbsp;
    </Dropdown>
    <Dropdown
      className="d-inline-block"
      // onMouseOver={this.onMouseEnter}
      // onMouseLeave={this.onMouseLeave}
      isOpen={this.state.dropdownOpen2}
      toggle={this.toggle2}
    >

      <DropdownToggle caret>Dropdown2</DropdownToggle>
      <DropdownMenu>
        <DropdownItem header>Submenu 2</DropdownItem>
        <DropdownItem>Submenu 2.1</DropdownItem>
        <DropdownItem>Submenu 2.2</DropdownItem>
      </DropdownMenu>
      &nbsp;&nbsp;&nbsp;
      <br /><br />

    </Dropdown>
    <Dropdown
      className="d-inline-block"
      // onMouseOver={this.onMouseEnter}
      // onMouseLeave={this.onMouseLeave}
      isOpen={this.state.dropdownOpen3}
      toggle={this.toggle3}
    >

      <DropdownToggle caret>Dropdown3</DropdownToggle>
      <DropdownMenu>
        <DropdownItem header>Submenu 3</DropdownItem>
        <DropdownItem>Submenu 3.1</DropdownItem>
        <DropdownItem>Submenu 3.2</DropdownItem>
        <DropdownItem>Submenu 3.3</DropdownItem>
      </DropdownMenu>
    </Dropdown>
  </div>

https://stackblitz.com/edit/reactstrap-v6-2dnzex?file=Example.js

答案 1 :(得分:0)

 import React from "react";
import {
  Dropdown,
  DropdownToggle,
  DropdownMenu,
  DropdownItem
} from "reactstrap";

export default class Example extends React.Component {
  constructor(props) {
    super(props);

    this.toggle = this.toggle.bind(this);
    this.onMouseEnter = this.onMouseEnter.bind(this);
    this.onMouseLeave = this.onMouseLeave.bind(this);
    this.state = {
      dropdownOpen1: false,
      dropdownOpen2: false,
      dropdownOpen3: false
    };
  }

  toggle(id) {
   this.setState({[id]:!this.state[`${id}`]})
  }

  onMouseEnter(id) {
    this.setState({ [id]: true });
  }

  onMouseLeave(id) {
    this.setState({ [id]: false });

  }

  render() {
    return (
      <div>
        <Dropdown
          className="d-inline-block"
          onMouseOver={()=>this.onMouseEnter("dropdownOpen1")}
          onMouseLeave={()=>this.onMouseLeave("dropdownOpen1")}
          isOpen={this.state.dropdownOpen1}
          toggle={()=>this.toggle("dropdownOpen1")}
        >
          <DropdownToggle caret>Dropdown1</DropdownToggle>
          <DropdownMenu>
            <DropdownItem header>Submenu 1</DropdownItem>
            <DropdownItem>Submenu 1.1</DropdownItem>
          </DropdownMenu>
        </Dropdown>
        <Dropdown
          className="d-inline-block"
           onMouseOver={()=>this.onMouseEnter("dropdownOpen2")}
          onMouseLeave={()=>this.onMouseLeave("dropdownOpen2")}
          isOpen={this.state.dropdownOpen2}
          toggle={()=>this.toggle("dropdownOpen2")}
        >
          &nbsp;&nbsp;&nbsp;
          <DropdownToggle caret>Dropdown2</DropdownToggle>
          <DropdownMenu>
            <DropdownItem header>Submenu 2</DropdownItem>
            <DropdownItem>Submenu 2.1</DropdownItem>
            <DropdownItem>Submenu 2.2</DropdownItem>
          </DropdownMenu>
        </Dropdown>
        <Dropdown
          className="d-inline-block"
        onMouseOver={()=>this.onMouseEnter("dropdownOpen3")}
          onMouseLeave={()=>this.onMouseLeave("dropdownOpen3")}
          isOpen={this.state.dropdownOpen3}
          toggle={()=>this.toggle("dropdownOpen3")}
        >
          &nbsp;&nbsp;&nbsp;
          <br />
          <br />
          <DropdownToggle caret>Dropdown3</DropdownToggle>
          <DropdownMenu>
            <DropdownItem header>Submenu 3</DropdownItem>
            <DropdownItem>Submenu 3.1</DropdownItem>
            <DropdownItem>Submenu 3.2</DropdownItem>
            <DropdownItem>Submenu 3.3</DropdownItem>
          </DropdownMenu>
        </Dropdown> 
      </div>
    );
  }
}

尝试一下!!!!让我知道,基本上,您需要为每个下拉列表传递不同的args,以便您的方法可以区分打开或关闭的内容。

答案 2 :(得分:0)

@TestUser和Drew Reese,您好我使用箭头功能减少了几行:https://stackblitz.com/edit/reactstrap-dropdown?file=Example.js,如果您需要n下拉菜单,则可以创建单个下拉菜单,并使用props可以为此创建多个下拉菜单(您可以使用地图重复此操作),并可以在多个地方使用。那就是反应之美。

答案 3 :(得分:0)

因此,基本上,所有三个下拉菜单都使用相同的状态变量。

要解决此问题,您需要维护三个不同的状态变量,因为您希望采用动态方式,可以遵循以下方法

对于可重用的方法,您还可以将Dropdown作为单独的组件。

如果需要,您可以添加更多逻辑,这是解决问题的简单方法

App.js

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { Container } from "reactstrap";
import CustomDropDown from "./CustomDropdown";
import "bootstrap/dist/css/bootstrap.min.css";

import "./styles.css";

const dropdownConfig = [
  {
    customKey: 1,
    options: [
      { title: "Submenu 1", header: true },
      { title: "Submenu 1.1", header: false }
    ],
    name: "dropdownOpen1"
  },
  {
    customKey: 2,
    options: [
      { title: "Submenu 2", header: true },
      { title: "Submenu 2.1", header: false }
    ],
    name: "dropdownOpen2"
  },
  {
    customKey: 3,
    options: [
      { title: "Submenu 3", header: true },
      { title: "Submenu 3.1", header: false }
    ],
    name: "dropdownOpen3"
  }
];

function App() {
  const [keysForDropdown, setKeysForDropdown] = useState({});

  useEffect(() => {
    const keys = dropdownConfig.map(dropdown => dropdown.name);
    const object = keys.reduce((acc, curr) => {
      acc[curr] = false;
      return acc;
    }, {});
    setKeysForDropdown({ ...object });
  }, []);

  const _handleToggle = e => {
    setKeysForDropdown({
      ...keysForDropdown,
      [e.target.name]: !keysForDropdown[e.target.name]
    });
  };

  const _handleMouseEnter = e => {
    setKeysForDropdown({
      ...keysForDropdown,
      [e.target.name]: !keysForDropdown[e.target.name]
    });
  };

  const _handleMouseLeave = e => {
    setKeysForDropdown({
      ...keysForDropdown,
      [e.target.name]: !keysForDropdown[e.target.name]
    });
  };

  return (
    <div className="App">
      <Container>
        {keysForDropdown &&
          dropdownConfig.map(dropdown => (
            <CustomDropDown
              {...dropdown}
              key={dropdown.customKey}
              stateKeys={keysForDropdown}
              handleToggle={_handleToggle}
              handleMouseEnter={_handleMouseEnter}
              handleMouseLeave={_handleMouseLeave}
            />
          ))}
      </Container>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

CustomDropdown.js

import React from "react";
import {
  Dropdown,
  DropdownToggle,
  DropdownMenu,
  DropdownItem
} from "reactstrap";

const CustomDropDown = props => {
  const {
    handleMouseEnter,
    handleMouseLeave,
    handleToggle,
    options,
    name,
    stateKeys
  } = props;
  return (
    <div className="dropdown-container">
      <Dropdown
        className="d-inline-block"
        onMouseOver={handleMouseEnter}
        onMouseLeave={handleMouseLeave}
        isOpen={stateKeys[name]}
        toggle={handleToggle}
      >
        <DropdownToggle name={name} caret>
          Dropdown1
        </DropdownToggle>
        <DropdownMenu>
          {options.length &&
            options.map(({ header, title }) => (
              <DropdownItem header={header}>{title}</DropdownItem>
            ))}
        </DropdownMenu>
      </Dropdown>
    </div>
  );
};

export default CustomDropDown;

工作https://github.com/quarkusio/quarkus/issues/2835

答案 4 :(得分:0)

这是我显示菜单或下拉菜单的子菜单的解决方案。 如果您对此有任何疑问或有任何疑问,请随时提出。

import React from 'react';
import { Box, jsx } from 'theme-ui';
import { Link } from 'gatsby';
import { H1 } from '../../components/ThemeHeader';
import { Image } from '../../components';

const CardWithCTALinks = (props) => {
  const { cardWithCTALinksImage, ctaLinks, heading, bgColor } = props;
  const [onCTAListHover, setOnCTAListHover] = React.useState({ status: '', indexAt: -1 });

  const updateCTAListHover = (newOnCTAListHover, idx) => {
    if (newOnCTAListHover !== onCTAListHover) setOnCTAListHover({ state: newOnCTAListHover, indexAt: idx });
  };
  const renderImageSection = (src, alt) => {
    return <Image src={src} alt={alt} />;
  };
  const renderSubLinks = (subLinks, idx) => {
    return (
      <Box>
        {idx === onCTAListHover.indexAt &&
          subLinks.map((link) => (
            <Link key={Math.random().toString(36).substring(7)} to="/">
              {link.text}
            </Link>
          ))}
      </Box>
    );
  };
  const renderLinksSection = (linksList, headingText) => {
    return (
      <Box>
        {headingText && <H1>{headingText}</H1>}
        {linksList && (
          <Box>
            {linksList.map((link, index) => (
              <h1 onMouseEnter={() => updateCTAListHover(true, index)} onMouseLeave={() => updateCTAListHover(false, index)}>
                {link.node?.title}
                {link.node?.navItems.length > 0 && <>{onCTAListHover && renderSubLinks(link.node?.navItems, index)}</>}
              </h1>
            ))}
          </Box>
        )}
      </Box>
    );
  };

  return (
    <Box style={{ backgroundColor: bgColor }}>
      {cardWithCTALinksImage && <Box>{renderImageSection(cardWithCTALinksImage?.asset._ref, 'alt')}</Box>}
      {ctaLinks && heading && <Box>{renderLinksSection(ctaLinks.edges, heading)}</Box>}
    </Box>
  );
};

export default CardWithCTALinks;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>