在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>
<DropdownToggle caret>Dropdown2</DropdownToggle>
<DropdownMenu>
<DropdownItem header>Submenu 2</DropdownItem>
<DropdownItem>Submenu 2.1</DropdownItem>
<DropdownItem>Submenu 2.2</DropdownItem>
</DropdownMenu>
<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
设置了dropDownOpen
和onMouseOver
等事件中onMouseLeave
的状态。
问题位于单个下拉菜单上,每个下拉菜单都被打开。
请帮助我将鼠标悬停在下拉菜单中,以便一次仅列出一个悬停的菜单,而并非全部。
注意:在我的实际应用中,这些下拉菜单将是动态的,因此我无法设置任何硬编码状态,例如dropDown1
,dropDown2
,dropDown3
...等等。
它可能有n
个下拉菜单。.因此,请在考虑动态菜单的情况下为我提供解决方案。
答案 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>
</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>
<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")}
>
<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")}
>
<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;
答案 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>