2017-09-13 19 views
2

私の反応アプリケーションでは、コンポーネントの1つでは、以下のようなボタンドロップダウンメニューが作成されています。メニュー領域の外をクリックまたはホバリングして反応ボタンのドロップダウンメニューを閉じる

<div class="dropdown"> 
    <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Dropdown Example 
    <span class="caret"></span></button> 
    <ul class="dropdown-menu"> 
     <li><a onClick=doSomething href="#">HTML</a></li> 
     <li><a onClick=doSomething href="#">CSS</a></li> 
     <li><a onClick=doSomething href="#">JavaScript</a></li> 
    </ul> 
</div> 

誰かがこのメニュー領域外のどこかをクリックするとこのメニューを閉じることができますか?

答えて

3

あなたのReact内でjQueryイベントとDOM操作を使用しないでください。ポイントがありません。
あなたはstateを使用しています。

次の例では、あなたは私がすべてのjquery.jsbootstrap.jsファイルを削除し、のみbootstrap.cssを保って見ることができます。
<ul>リストを表示/非表示にするにはstateを使用しています(display: nonebootstrap.cssに置き換えるためにdisplay: blockに設定しました)。 - ボタンのonBlurに取り付けstateshowプロパティを切り替える

  1. toggleShow()
    Iが示す各項目のonclickため<ul>と1ハンドラを隠すについて2つのメインハンドラを設定しています。
  2. hide() - 私はもちろん説明しているものを としていますが、<ul>を隠しています。
  3. doSomething() - アイテムをクリックすると起動します。

<ul>を隠すと、このシナリオはクリックイベントを処理できません。

なぜですか?

state.showがfalseの場合、実際には隠すわけではないため、レンダリングされません。だから、基本的にはsetStateの競合条件があり、実行できないイベントハンドラdoSomethingのハンドラに対してトリガが再描画されます。
ボタンのonBlurイベントをトリガしたアクティブな要素が<ul>の項目であるかどうかを判断することです。そうであれば、項目をonClickというイベントでトリガーさせ、次に状態を設定して「隠す」必要があります。
eventに添付されているrelatedTargetの助けを借りて、それを行いました。これは私たちが探している能動的な要素であり、もしそれがなければnullであり、クリックイベント(私たちが気にしないような要素であっても)をトリガーし、状態はshow: falseです。

作業例:

class DropDown extends React.Component{ 
 
    constructor(props){ 
 
    super(props); 
 

 
    this.state = { 
 
     show: false 
 
    } 
 
    this.doSomething = this.doSomething.bind(this); 
 
    this.toggleShow = this.toggleShow.bind(this); 
 
    this.hide = this.hide.bind(this); 
 
    } 
 

 
    doSomething(e){ 
 
    e.preventDefault(); 
 
    console.log(e.target.innerHTML); 
 
    } 
 

 
    toggleShow(){ 
 
    this.setState({show: !this.state.show}); 
 
    } 
 

 
    hide(e){ 
 
    if(e && e.relatedTarget){ 
 
     e.relatedTarget.click(); 
 
    } 
 
    this.setState({show: false}); 
 
    } 
 
    
 
    render(){ 
 
    return(
 
     <div className="dropdown"> 
 
     <button 
 
      className="btn btn-primary dropdown-toggle" 
 
      type="button" 
 
      onClick={this.toggleShow} 
 
      onBlur={this.hide} 
 
     > 
 

 
     {"Dropdown Example"} 
 
      
 
     <span className="caret"></span> 
 
     </button> 
 
     { 
 
      this.state.show && 
 
     (
 
      <ul className="dropdown-menu" style={{display: 'block'}}> 
 
      <li><a onClick={this.doSomething} href="#">HTML</a></li> 
 
      <li><a onClick={this.doSomething} href="#">CSS</a></li> 
 
      <li><a onClick={this.doSomething} href="#">JavaScript</a></li> 
 
     </ul> 
 
     ) 
 
     } 
 
     </div> 
 
    ); 
 
    } 
 
} 
 

 

 
ReactDOM.render(<DropDown />, document.getElementById('root'));
<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> 
 

 
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> 
 
<div id="root"></div>

+0

OPが要求しているホバーアウトエフェクトを取得するには、 'ul'に' onMouseLeave = {this.hide} 'を追加してください。 – totbar

+0

@totbarロジックを少し変更する必要があります。マウスを外すとそれを隠すと、クリックすることはできません。 OPの横にマウスがどこにどこに正確に取り付けられるべきか明確ではなかった。もちろんそれは可能です。 –

1

これを行うにはいくつかの方法があります。これを達成する最も簡単な方法は、イベントリスナーがクリックイベントを聴いたり、ドロップダウンコンポーネントのonBlur関数を記述したりすることです。

componentWillMount() { 
    document.body.addEventListener('click', this.handleClick); 
    } 

    componentWillUnmount() { 
    document.body.removeEventListener('click', this.handleClick); 
    } 

次に、コンポーネントをリスナーコンポーネント内にラップする必要があります。

ここでは、動作しているJSのフィドルです。 https://jsfiddle.net/vamshikrishna144/zukcpfr2/

+0

あなたは同じボタンやメニューを取得するために、ブートストラップを使用している可能性があり、外側のクリックに近いメニュー操作を実証していることができれば、それはもっと良かったはず –

+0

@LokeshAgrawalしかし、それは質問の一部ではありません:)あなたの懸念事項は何ですか? –

関連する問題