我想在 React 中做一个下拉菜单。单击一个按钮应打开一个子菜单。在子菜单之外单击应将其关闭

Posted

技术标签:

【中文标题】我想在 React 中做一个下拉菜单。单击一个按钮应打开一个子菜单。在子菜单之外单击应将其关闭【英文标题】:I want to make a dropdown in React. Clicking a button should open a submenu. Clicking outside of the submenu should close it 【发布时间】:2016-02-29 15:27:22 【问题描述】:

这是我现有的工作代码。这很好用,除了如果我在子菜单之外单击,当它打开时,子菜单保持打开状态。

class UserTypeDropdown extends React.Component
  constructor: (props) ->
    super(props)
    @state =
      display_submenu: false
  @propTypes:
    selected: React.PropTypes.string.isRequired

  submenu_display:->
    if @state.display_submenu
      'block'
    else
      'none'
  button_class_names:->
    classNames(
        'select-btn ': true,
        'user_role ': @props.selected is 'user',
        'admin_role ': @props.selected is 'admin'
        )

  selected_text:->
    if @props.selected == 'user'
      'User'
    else
      'Administrator'

  render:->
    div className: 'user-type-dropdown',
      button  className: @button_class_names(), onClick: @_toggleSubmenu ,
        @selected_text()
      ul className: 'submenu submenu_content access_submenu', style: display: @submenu_display(),
        li onClick: @select_admin,
          a ,
            'Administrator'
        li onClick: @select_user,
          a ,
            'User'
  _toggleSubmenu: =>
    @setState display_submenu: !@state.display_submenu
  select_admin: =>
    @_toggleSubmenu()
    actions.setUserRole('admin')
  select_user: =>
    @_toggleSubmenu()
    actions.setUserRole('user')

我想实现在子菜单打开时单击外部,然后将其关闭。

我已经阅读了如何在 React 中执行此操作,并且遇到了很多建议说我应该使用 onFocus 和 onBlur 而不是 onClick

这对我来说很有意义,因为这意味着下拉菜单应该只有在浏览器中处于焦点时才应该打开。所以我的渲染函数和方法就变成了。

  render:->
    div className: 'user-type-dropdown',
      button  className: @button_class_names(), onFocus: @_toggleSubmenu, onBlur: @_toggleSubmenu ,
        @selected_text()
      ul className: 'submenu submenu_content access_submenu', style: display: @submenu_display(),
        li onClick: @select_admin,
          a ,
            'Administrator'
        li onClick: @select_user,
          a ,
            'User'
  _toggleSubmenu: =>
    @setState display_submenu: !@state.display_submenu
  select_admin: =>
    actions.setUserRole('admin')
  select_user: =>
    actions.setUserRole('user')

但是在 button 元素上使用 onFocus:onBlur:, 现在点击li 中的任何一个都不会触发@select_admin@select_user,它只会触发@_toggle_submenu,并且点击似乎不会传播/冒泡到下面的li 元素。。

通过阅读React Event Documentation 和This Focus and hotkeys guide,我可以看到这些事件应该会冒泡,但对我来说根本不是。

我是 React Coffescript/JS 世界的新手,所以请原谅任何不正确的命名约定。

我认为我的理解一定有缺陷,因为我在任何地方都找不到这个问题的答案。

任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

您的问题是:一旦您单击一个项目,onBlur 事件就会首先触发。这会导致重新渲染(因为您执行setState)。因此,您的 onClick 事件永远不会运行。

解决这个问题的方法(使用 onFocus 和 onBlur)是重新排列您的 html 设置:

确保您的主菜单项能够获得焦点(<button> 已经可以了) 确保您的子菜单没有焦点(<li> 可以) 确保您的子菜单位于主菜单组件内(您需要更改此设置)

这样,如果您单击其中一个子项,您的主菜单项就不会失去焦点。

您可以找到一个简单的(仅限 HTML 和 javascript)JSBIN example here。

【讨论】:

这很有意义。我从我们之前的非反应设计中继承了 html 结构,并且从未想过要更改它。明天我会更新结构,让你知道我的进展如何!谢谢:) 效果很好,非常感谢@wintvelt!

以上是关于我想在 React 中做一个下拉菜单。单击一个按钮应打开一个子菜单。在子菜单之外单击应将其关闭的主要内容,如果未能解决你的问题,请参考以下文章

React 下拉菜单只切换一次

出现在 div 之外的下拉菜单

没有下拉菜单的 Qt 菜单栏(单级菜单栏)

如何在 django 中添加项目下拉菜单

Reactstrap 下拉菜单打开倍数菜单

选择/打开新下拉列表时自动关闭下拉列表(React)