2015-09-14 12 views
13

Diciamo che ho nidificati componenti in questo modo:Reagire: bubbling degli eventi attraverso i componenti nidificate

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

Voglio fare cliccando sul bersaglio eseguire una funzione di radice:

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

Devo imposta manualmente una proprietà su ogni componente della catena, come nell'esempio del tutorial 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> 

O c'è qualche modo per bolla gli eventi fino, come in DOM normale?

risposta

3

È possibile utilizzare la scorciatoia per passare oggetti di scena attraverso componenti figlio

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

Transferring props

Quindi nel tuo caso:

<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> 
+11

Anche se questa è la risposta accettata, quella corretta è quella sotto riportata. –

+0

Mentre {... this.props} funziona, rende davvero difficile ragionare sui componenti che vengono trasmessi, dopo aver mantenuto un progetto con centinaia di componenti che è impossibile da tracciare. – Patrick

+0

@Patrick puoi provare [Redux] (http://redux.js.org/). Introduce un concetto 'selector', che ti permette di selezionare i puntelli da un archivio dati globale invece di passare oggetti di scena dal genitore – sundayku

22

Reagire supporta eventi sintetici attraverso di esso di Dom virtuale sia in fasi di cattura e gorgogliamento (come descritto qui: https://facebook.github.io/react/docs/events.html).

Questo significa che si potrebbe mettere un gestore onClick su qualsiasi elemento DOM vicino alla radice e dovrebbe far scattare per tutti gli eventi fare clic sulla pagina:

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

Tuttavia, dal momento che il fuoco per tutto click eventi, dovresti disambiggerli tra loro nel gestore dei clic (il che rende il codice piuttosto brutto).

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 
    } 
} 

Questo stile di delegazione evento è in realtà ciò che Reagire fa sotto il cofano (https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation) quindi bisogna chiedersi se questo è ciò che si vuole veramente fare.

In alternativa si potrebbe voler guardare qualcosa come il modello Dispatcher in Flux (https://facebook.github.io/flux/docs/actions-and-the-dispatcher.html#content). È un po 'più complicato andare avanti, ma nel complesso è una soluzione migliore.

+1

Ho pensato che non dovresti mutare gli oggetti di scena? – kapsi

+0

Penso che tu abbia ragione, rimuovendo quel para. – chrismilleruk

+1

«per tutti gli eventi Click sulla pagina» È più corretto dire, per tutti i discendenti (nodi interni). – amirouche