2017-06-17 3 views
1

Ich habe mehrere benutzerdefinierte Build Dropdown-Komponente von reagieren auf einer Seite. Ich auslösen den Listeneintrag setState mit öffnenKlicken Sie auf eine beliebige Stelle, um Drop-Down in Reaktion zu schließen

toggleDropdown = (id) => { 
     this.setState(prevState => ({ 
      [`dropdown${name}`]: !prevState[`dropdown${id}`] //dropdownA, dropdownB, dropdownC and so on 
     })) 
    } 

das wird es auch wechseln, wenn der Drop-Down geklickt wurde, wenn das Menü geöffnet ist. Aber dann habe ich noch ein paar Dropdowns, ein anderes Dropdown wird nicht geschlossen, wenn ich ein Dropdown öffne, wie löst man das? Ich mache eine "hacky" Art und Weise zu reagieren mit jquery in ComponentWillMount, Bindung Click-Ereignis auf Körper, überprüfen Sie, ob das Dropdown-Element sichtbar ist, wenn ja, schließen Sie es.

Meine Frage ist, gibt es eine bessere Praxis zu vermeiden, mit Jquery?

+0

können Sie ein Beispiel für Ihre app.js zur Verfügung stellen? –

Antwort

3

Mein Vorschlag ist, dass Sie die synthetischen Ereignisse verwenden onFocus und onBlur Öffnen/Schließen Zustand auszulösen. onFocus wird ausgelöst, wenn auf das Element geklickt wird und onBlur wird ausgelöst, wenn "unfocusing" (Klicken außerhalb). Siehe docs.

Auch das Attribut tabIndex wird benötigt, damit Fokus/Unschärfe auf Elementen ohne Eingabe funktioniert.

Ich kann empfehlen, die source of react-select zu betrachten und wie sie Fokussierung/Bluring behandeln. Hier

ist ein Beispiel, können Sie eine Demo davon sehen here

import React from 'react' 

class Dropdown extends React.Component { 

    constructor(props) { 
    super(props); 

    this.state = { 
     open: false 
    }; 
    } 

    toggleDropdown() { 
    this.setState({open: !this.state.open}); 
    } 

    render() { 
    return (
     <div 
     style={{border: '1px solid #CCC'}} 
     onBlur={() => this.toggleDropdown()} 
     onFocus={() => this.toggleDropdown()} 
     tabIndex='0' 
     > 
     Dropdown 
     { this.state.open && 
      <div> 
      <div>Red</div> 
      <div>Green</div> 
      <div>Blue</div> 
      </div> 
     } 
     </div> 
    ); 
    } 

} 

export default Dropdown; 
+1

brilliante Lösung, vielen Dank –

+0

@heyhugo wissen Sie, wie die Kinder Elemente ('

Red
') auch ohne die Minimierung der Eltern zu focasable? –

+0

@JohnCullen verwenden Sie node.contains() (Browser-DOM) API, um zu überprüfen, ob das übergeordnete Element das angeklickte Element enthält. Sie können sehen, wie es hier gemacht werden kann: https://github.com/JedWatson/react-select/blob/master/src/Select.js#L223 – heyhugo

0

Sie könnten die react-onclickoutside-Bibliothek verwenden, die das Body-Event-Handling für Sie abstrahiert. Sie müssen nur Ihre Komponente in ihre onClickOutside Komponente höherer Ordnung wickeln, die den Rückruf handleClickOutside immer dann ausführt, wenn der Klick außerhalb des Dropdown-Menüs erfolgt. Auf diese Weise können Sie in allen Dropdown-Listen einen privaten "offenen" Status haben und sich nicht darum kümmern, wie die Handhabung erfolgt.

Der Code könnte so aussehen:

import React, { Component } from 'react' 
import onClickOutside from 'react-onclickoutside' 

class Dropdown extends Component { 
    constructor() { 
     this.state = {open: false} 
    } 

    // Method automatically executed by the library. 
    handleClickOutside() { 
     this.setState({open: false}) 
    } 

    render() { ... } 
} 

export default onClickOutside(Dropdown) 
Verwandte Themen