React: событие, пузырящееся через вложенные компоненты
Скажем, у меня есть вложенные компоненты вроде этого:
<root />
<comp1 />
<comp2 />
<target id={this.props.id}>
<div>click me</div>
Я хочу, чтобы щелчок на целевой странице выполнял функцию root:
//on root component
this.action = function(id){}
Нужно ли вручную задавать свойство для каждого компонента в цепочке, например, в примере с руководством 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>
Или есть способ, чтобы пузырить события вверх, как в обычном DOM?
Ответы
Ответ 1
Вы можете использовать стенографию, чтобы передать реквизиты дочерним компонентам
<Component {...this.props} more="values" />
Перенос реквизита
Итак, в вашем случае:
<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>
Ответ 2
React поддерживает Synthetic Events через него Virtual DOM как на этапах захвата, так и в пузырьках (как описано здесь: https://facebook.github.io/react/docs/events.html).
Это означает, что вы можете поместить обработчик onClick на любой элемент DOM рядом с корнем, и он должен запускать для всех событий Click на странице:
<root>
<div onClick={this.handleAllClickEvents}>
<comp1>
<comp2>
<target>
<div id={this.props.id}>click me</div>
Однако, поскольку он будет срабатывать для всех событий кликов, вам нужно будет устранить двусмысленность между ними в обработчике кликов (что делает некоторый довольно уродливый код).
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
}
}
Этот стиль делегирования событий на самом деле является тем, что React делает под капотом (https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation), поэтому вы должны спросить себя, что именно вы действительно хотите сделать.
В качестве альтернативы вы можете посмотреть что-то вроде шаблона Dispatcher в Flux (https://facebook.github.io/flux/docs/actions-and-the-dispatcher.html#content). Это немного сложнее, но это лучшее решение в целом.