简体   繁体   English

如何在 reactjs 中添加下拉菜单?

[英]How to add dropdown in reactjs?

I am making a simple react application where the requirement is that I need to make dropdown using pure reactjs .. And the dropdown needs to be responsive as well.我正在制作一个简单的反应应用程序,其要求是我需要使用纯 reactjs制作下拉列表。下拉列表也需要响应。

The following mouse/click events are expected.预期会出现以下鼠标/单击事件。

  • Larger devices like Desktop screens: On hover较大的设备,如桌面屏幕:在 hover
  • Smaller devices like Mobile: On click移动设备等较小的设备:点击

Working Snippet工作片段

 function App() { React.useEffect(() => { const has_submenu = document.querySelector(".has-submenu"); const submenu = document.querySelector(".submenu"); const submenu_height = submenu && submenu.childElementCount * 34; if (has_submenu && submenu && submenu_height) { has_submenu.addEventListener("mouseover", function () { submenu.style.height = submenu_height + "px"; }); has_submenu.addEventListener("mouseout", function () { submenu.style.height = "0px"; }); submenu.addEventListener("mouseover", function () { submenu.style.height = submenu_height + "px"; }); submenu.addEventListener("mouseout", function () { submenu.style.height = "0px"; }); } }, []); return ( <nav> <ul> <li className="menu-item has-submenu inline-flex"> Account </li> <ul className="submenu"> <li className="submenu-item submenu1"> Profile </li> <li className="submenu-item submenu1"> Change Password </li> </ul> </ul> </nav> ); } ReactDOM.render(<App />, document.querySelector('#app'));
 .submenu { background: #fff; position: absolute; list-style-type: none; padding: 0; height: 0px; overflow: hidden; color: #000; cursor: pointer; transition: height 0.33333s ease-in; }.submenu-item { padding: 2px 16px; list-style-position: outside; transition: background 0.33333s; }
 <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script> <div id="app"></div>

If you take a look at the above code, then you could able to see that on mouse hover account , the sub menus are listed down.如果你看一下上面的代码,那么你可以看到在鼠标 hover account上,子菜单被列出来了。

Requirement:要求:

Even though it works, I feel that I have achieved it using the scope outside react because I am using dom methods and setting up height to the submenu part.尽管它有效,但我觉得我已经使用 scope 外部反应实现了它,因为我正在使用dom methods并设置submenu部分的高度。

Is there any pure react way of achieving this?是否有任何纯粹的反应方式来实现这一目标?

If so kindly please help me to refactor the above snippet to achieve the dropdown of menus in both desktop view (on hover) and mobile view (on click)..如果好心,请帮助我重构上面的代码片段,以实现桌面视图(悬停时)和移动视图(点击时)中的菜单下拉..

Expected output:预期 output:

Desktop: (On hover)桌面:(悬停时)

 Dashboard      Account               Logout
                | -- Profile -- |
                | -- Change Password -- |

Mobile: (On click)手机:(点击)

  Dashboard

  Account 

    | -- Profile -- |
    | -- Change Password -- |

 Logout

React allows you to control state within your components. React 允许你在你的组件中控制state There are many ways to handle this, but I'll give a small example below.有很多方法可以解决这个问题,但我将在下面给出一个小例子。

You will want to react to events and change the state .您将需要对事件做出反应并更改state Every time the state updates, your component will be re-rendered.每次state更新时,您的组件都会重新渲染。

 const MAGIC_NUMBER = 34; const MyApp = () => { const subMenuRef = React.createRef(); const [ isMenuOpen, setMenuOpen ] = React.useState(false); const [ menuHeight, setMenuHeight ] = React.useState(0); const openMenu = () => setMenuOpen(true); const closeMenu = () => setMenuOpen(false); React.useEffect(() => { if (.subMenuRef;current) { return. } setMenuHeight(subMenuRef.current;childElementCount * MAGIC_NUMBER), }. [subMenuRef;current]): return ( <nav> <ul> <li className="menu-item inline-flex" onMouseOver={openMenu} onMouseOut={closeMenu} > Account </li> <ul className="submenu" ref={subMenuRef} style={{height? isMenuOpen: menuHeight; 0}} onMouseOver={openMenu} onMouseOut={closeMenu} > <li className="submenu-item submenu1"> Profile </li> <li className="submenu-item submenu1"> Change Password </li> </ul> </ul> </nav> ); }. ReactDOM,render(<MyApp />. document;querySelector('#app'));
 .submenu { background: #fff; position: absolute; list-style-type: none; padding: 0; height: 0px; overflow: hidden; color: #000; cursor: pointer; transition: height 0.33333s ease-in; border: 1px solid #777; }.submenu-item { padding: 2px 16px; list-style-position: outside; transition: background 0.33333s; }
 <script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script> <div id="app"></div>

There is a lot going on above, so I'll try to break it down here..上面发生了很多事情,所以我会尝试在这里分解它..

  • We added event listeners directly to our elements.我们将事件侦听器直接添加到我们的元素中。
    • React allows us to directly attach these event listeners without accessing the DOM React 允许我们直接附加这些事件监听器,而无需访问 DOM
  • We added some state to keep track of the open/close state of the menu我们添加了一些 state 来跟踪菜单的打开/关闭 state
    • Inside our event handlers, we simply flip the state and everything works.在我们的事件处理程序中,我们只需翻转 state,一切正常。
    • We add conditional logic to our elements to handle the change in state.我们将条件逻辑添加到我们的元素中以处理 state 中的更改。 (Changing the height when the menu opens/closes) (在菜单打开/关闭时更改高度)
  • We used a ref to access the DOM directly to get the child element count.我们使用ref直接访问 DOM 以获取子元素计数。 Documentation文档
    • If you are completely in react, these children are probably a list that you're iterating over and you could simply get the length of that.如果你完全反应,这些孩子可能是你正在迭代的列表,你可以简单地得到它的长度。
    • In general you don't need to access the underlying DOM as most things will be handled within react itself.一般来说,您不需要访问底层 DOM,因为大多数事情都将在 react 本身中处理。

PS: Avoid using magic numbers wherever possible. PS:尽可能避免使用幻数。 In this case, you have a value of 34 .在这种情况下,您的值为34 What does this represent?这代表什么? Why is it here?为什么会在这里? If you must use exact heights, rely instead on css calculations using rem or lineHeight如果您必须使用精确的高度,请改用使用remlineHeight的 css 计算

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM