以编程方式在React中触发onBlur

4
我使用 onBlur 以关闭下拉菜单,但我也想处理 li 元素的点击事件,li 元素是在下拉菜单内部渲染的。在这里,setState 将无法正常工作,因为用户再次尝试打开下拉菜单时,行为会出现问题。可以在这里尝试:http://jsfiddle.net/ur1rbcrz
我的代码:
toggleDropdown = () => {
    this.setState({
        openDropdown: !this.state.openDropdown
    })
  }

  render() {
    return (
      <div>
        <div tabIndex="0" onFocus={this.toggleDropdown} onBlur={this.toggleDropdown}>
          MyList
        <ul className={this.state.openDropdown ? 'show' : 'hide'}>
          <li>abc</li>
          <li>123</li>
          <li onClick={()=> this.setState({openDropdown:false})}>xyz</li> {/* not working */}
        </ul>
      </div>
      </div>
    );
  }
3个回答

6

你的代码无法正常工作,因为尽管你点击了 li 元素,但是带有 onBlur 事件的 div 容器仍然保持焦点。

我们在你的列表容器中添加了 ref,之后我们可以调用 .blur() 方法。我们在你的 onClick li 事件处理程序中使用它。

this.dropDownList.blur()

请参见工作示例jsfiddle

或运行此片段:

class Hello extends React.Component {
  constructor() {
    super()
    this.state = {
      isDropdownVisible: false
    }
    
    this.toggleDropdown = this.toggleDropdown.bind(this);
  }
  
  toggleDropdown() {
   this.setState({
     isDropdownVisible: !this.state.isDropdownVisible
    })
  }
  
  render() {
    return (
      <div>
        <div 
        tabIndex="0" 
        ref={c => this.dropDownList = c}
        onFocus={this.toggleDropdown} 
        onBlur={this.toggleDropdown}>
          MyList
        <ul
        className={this.state.isDropdownVisible ? 'show' : 'hide'}>
          <li>abc</li>
          <li>123</li>
          <li onClick={() => this.dropDownList.blur()}>xyz</li> {/* not working */}
        </ul>
      </div>
      </div>
    );
  }
}

ReactDOM.render(
  <Hello initialName="World"/>,
  document.getElementById('container')
);
.hide {
  display: none
}

.show {
  display: block !important;
}

div:focus {
  border: 1px solid #000;
}

div:focus {
  outline: none;
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="container">
  <!-- This element's contents will be replaced with your component. -->
</div>


我使用toggle而不是hide和show处理程序来避免2个函数。 - Celdric Kang
@CeldricKang 这样调试和维护代码更容易。代码可以运行,我这里没有看到问题。 - loelsonk
@CeldricKang,让我更新一下,这样我们就可以使用“切换”而不是“显示”、“隐藏”。 - loelsonk
@CeldricKang 好的,我已经更新了我的答案。如果您认可,请接受它。 - loelsonk

0

OnBlur是React合成事件,可以有两种用法:

  1. 触发某些操作:

const {useState} = React;

const Example = ({title}) => {
  const [field, setField] = useState("");

  return (
    <div>
      <p>{title}</p>
      <p>Uppercase on blur</p>
      <input type="text" 
      value={field} 
      onChange={e=>setField(e.target.value)}
      //LOOK HERE !
      onBlur={e=>setField(e.target.value.toUpperCase())}
      />
    </div>
  );
};

// Render it
ReactDOM.render(
  <Example title="OnBlur triggering:" />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

  • 被某事触发
  • const {
      useState,
    } = React;
    
    const Example = ({
      title
    }) => {
      const [field, setField] = useState("");
    
      return ( <
        div >
        <
        p > {
          title
        } < /p> <
        p > Remove focus by pressing enter < /p> <
        input type = "text"
        value = {
          field
        }
        onChange = {
          e => setField(e.target.value)
        }
        //LOOK HERE !
        onBlur = {
          e => setField(e.target.value.toUpperCase())
        }
        onKeyPress = {
          e => (e.key === 'Enter' ? setField(e.target.value.toLowerCase()) || e.target.blur() : null)
        }
        /> < /
        div >
      );
    };
    
    // Render it
    ReactDOM.render( <
      Example title = "OnBlur triggered:" / > ,
      document.getElementById("react")
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
    <div id="react"></div>

    因此,在React中编程地触发onBlur,需要添加一个事件来监视您的更改。

    更多信息: React合成事件


    0
    我在你的 div 上添加了 onClick 事件,它可以正常工作,你的代码变成了:
      render() {
    return (
      <div>
        <div tabIndex="0" onClick={() => this.setState({openDropdown: !this.state.openDropdown})} onFocus={this.toggleDropdown} onBlur={this.toggleDropdown}>
          MyList
        <ul className={this.state.openDropdown ? 'show' : 'hide'}>
          <li>abc</li>
          <li>123</li>
          <li onClick={()=> this.setState({openDropdown:false})}>xyz</li> {/* not working */}
        </ul>
      </div>
      </div>
    );
    

    }


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接