web-dev-qa-db-de.com

Reagieren: Ereignis sprudelt durch verschachtelte Komponenten

Nehmen wir an, ich habe Komponenten wie diese verschachtelt:

<root />
  <comp1 />
    <comp2 />
      <target id={this.props.id}>
        <div>click me</div>

Ich möchte, dass ein Klick auf target eine Funktion auf root ausführt:

//on root component
this.action = function(id){}

Muss ich für jede Komponente in der Kette eine Eigenschaft manuell festlegen, wie im Lernbeispiel von React? Jsfiddle

<root />
  <comp1 clickHandler={this.action}/>
    <comp2 clickHandler={this.clickHandler}/>
      <target id={this.props.id} clickHandler={this.clickHandler} />
        <div onClick={this.props.clickHandler.bind(this, this.props.id)}>click me</div>

Oder gibt es eine Möglichkeit, die Ereignisse wie in einem normalen DOM aufzublähen?

18
kapsi

Sie können die Abkürzung verwenden, um Requisiten an untergeordnete Komponenten zu übergeben

<Component {...this.props} more="values" />

Requisiten übertragen

Also in deinem Fall:

<root />
  <comp1 clickHandler={this.action}/>
    <comp2 {...this.props} />
      <target {...this.props} id={this.props.id} />
        <div onClick={this.props.clickHandler.bind(this, this.props.id)}>click me</div>
4
Clarkie

React unterstützt Synthetic Events in seinem gesamten virtuellen DOM in der Capture- und Bubbling-Phase (wie hier beschrieben: https://facebook.github.io/react/docs/events.html ).

Dies bedeutet, dass Sie einen onClick-Handler auf ein beliebiges DOM-Element in der Nähe des Stammverzeichnisses setzen können, das für alle Click-Ereignisse auf der Seite ausgelöst werden sollte:

<root>
  <div onClick={this.handleAllClickEvents}>
    <comp1>
      <comp2>
        <target>
          <div id={this.props.id}>click me</div>

Da es jedoch für alle -Klickereignisse ausgelöst wird, müssten Sie im Click-Handler zwischen diesen unterscheiden (was für ziemlich hässlichen Code sorgt).

function handleAllClickEvents(event) {
  var target = event.relatedTarget;
  var targetId = target.id;
  switch(targetId) {
    case 'myBtn1':
      // handle myBtn1 click event
    case 'myBtn2':
      // handle myBtn2 click event
  }
}

Dieser Stil der Ereignisdelegation ist eigentlich das, was React unter der Haube tut ( https://shripadk.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-und -event-delegation ) Sie müssen sich also fragen, ob Sie das wirklich wollen.

Alternativ können Sie sich etwa das Dispatcher-Muster in Flux ansehen ( https://reactjs.org/blog/2014/07/30/flux-actions-and-the-dispatcher.html ). Es ist etwas komplizierter, aber es ist insgesamt eine bessere Lösung.

29
chrismilleruk

Wenn Sie unterscheiden möchten, welches Element am Ende angeklickt wurde, können Sie das Event-Objekt verwenden und dort einige interessante Informationen finden, wie z. B. den DOM-Elementtyp.

<AnElement>
 <button onClick={e => this.eventHandler(e)}>Click me</button>
 <input type="text" onClick={e => this.eventHandler(e)}>Click me</input>

eventHandler = (e) => {
        console.log(e, e.nativeEvent.toElement.nodeName);
...}

Und Sie erhalten button oder input, je nachdem, was Sie angeklickt haben . Das ist, wonach ich für mein Projekt gesucht habe. 

Darüber hinaus finden Sie möglicherweise einen DOM-Baum in einer Array-Darstellung  array representation

Ich hoffe es hilft

0
AlexNikonov