Реакция предотвращает пузырьки событий во вложенных компонентах при щелчке
Вот базовый компонент. У функций <ul>
и <li>
есть функции onClick. Я хочу только onClick на <li>
, а не <ul>
. Как я могу достичь этого?
Я играл с e.preventDefault(), e.stopPropagation(), но безрезультатно.
class List extends React.Component {
constructor(props) {
super(props);
}
handleClick() {
// do something
}
render() {
return (
<ul
onClick={(e) => {
console.log('parent');
this.handleClick();
}}
>
<li
onClick={(e) => {
console.log('child');
// prevent default? prevent propagation?
this.handleClick();
}}
>
</li>
</ul>
)
}
}
// => parent
// => child
Ответы
Ответ 1
Я была такая же проблема. Я обнаружил, что StopPropagation работает. Я бы разделил элемент списка на отдельный компонент следующим образом:
class List extends React.Component {
handleClick = e => {
// do something
}
render() {
return (
<ul onClick={this.handleClick}>
<ListItem onClick={this.handleClick}>Item</ListItem>
</ul>
)
}
}
class ListItem extends React.Component {
handleClick = e => {
e.stopPropagation(); // <------ Here is the magic
this.props.onClick();
}
render() {
return (
<li onClick={this.handleClick}>
{this.props.children}
</li>
)
}
}
Ответ 2
React использует делегирование событий с одним прослушивателем событий в документе для событий, которые пузырятся, например 'click' в этом примере, что означает, что прекращение распространения невозможно; реальное событие уже распространилось к тому моменту, когда вы взаимодействуете с ним в React. stopPropagation on React синтетическое событие возможно, потому что React обрабатывает распространение синтетических событий внутри.
stopPropagation: function(e){
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
}
Ответ 3
Это не на 100% идеально, но если вам слишком сложно передавать props
в детской → детской моде или создавать Context.Provider
/Context.Consumer
только для этой цели), и вы имеете дело с другой библиотекой у которого есть собственный обработчик, он запускается раньше вашего, вы также можете попробовать:
function myHandler(e) {
e.persist();
e.nativeEvent.stopImmediatePropagation();
e.stopPropagation();
}
Насколько я понимаю, метод event.persist
предотвращает немедленное возвращение объекта в пул React SyntheticEvent
. Поэтому из-за этого event
переданное в React, на самом деле не существует к тому времени, когда вы его достигнете! Это происходит у внуков из-за способа, которым React обрабатывает вещи внутренне, сначала проверяя родительский элемент на наличие обработчиков SyntheticEvent
(особенно, если у родителя был обратный вызов).
Пока вы не вызываете persist
для чего-то, что могло бы создать значительную память для продолжения создания событий, таких как onMouseMove
(и вы не создаете какую-либо игру Cookie Clicker, такую как Grandma Cookies), все должно быть прекрасно!
Также обратите внимание: из-за периодического чтения их GitHub мы должны не спускать глаз с будущих версий React, так как они могут в конечном итоге решить некоторые проблемы с этим, поскольку они, похоже, собираются делать свертывание кода React в компиляторе/транспортере.
Ответ 4
У меня были проблемы с получением event.stopPropagation()
. Если вы тоже это сделаете, попробуйте переместить его в верхнюю часть функции-обработчика кликов, это было то, что мне нужно было сделать, чтобы событие не всплывало. Пример функции:
toggleFilter(e) {
e.stopPropagation(); // If moved to the end of the function, will not work
let target = e.target;
let i = 10; // Sanity breaker
while(true) {
if (--i === 0) { return; }
if (target.classList.contains("filter")) {
target.classList.toggle("active");
break;
}
target = target.parentNode;
}
}
Ответ 5
Вы можете избежать пузырей события, проверив цель события.
Например, если вы вложили вложенный элемент div, где у вас есть обработчик для события click, и вы не хотите обрабатывать его, при нажатии на вход вы можете просто передать event.target
в свой обработчик и проверить, что обработчик должен быть выполняется на основе свойств цели.
Например, вы можете проверить, if (target.localName === "input") { return}
.
Итак, это способ "избежать" выполнения обработчика
Ответ 6
Новый способ сделать это намного проще и сэкономит вам время! Просто передайте событие в исходный обработчик щелчка и вызовите preventDefault();
,
clickHandler(e){
e.preventDefault();
//Your functionality here
}