これが基本的なコンポーネントです。 <ul>
と<li>
の両方にonClick関数があります。 <li>
ではなく、<ul>
のonClickのみを起動するようにします。どうすればこれを達成できますか?
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
同じ問題がありました。 stopPropagation did workが見つかりました。次のように、リストアイテムを個別のコンポーネントに分割します。
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();
this.props.onClick();
}
render() {
return (
<li onClick={this.handleClick}>
{this.props.children}
</li>
)
}
}
Reactは、この例の「クリック」のようにバブルするイベントに対して、ドキュメント上の単一のイベントリスナーでイベント委任を使用します。つまり、伝播を停止することはできません。実際のイベントは、Reactでイベントと対話するまでに既に伝播しています。 Reactは内部的に合成イベントの伝播を処理するため、Reactの合成イベントでstopPropagationが可能です。
stopPropagation: function(e){
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
}
これは100%理想的ではありませんが、子供のprops
を引き継ぐのが非常に苦痛であるか、子供のファッションを作成するか、この目的のためにContext.Provider
/Context.Consumer
を作成する場合just)あなたの前に実行する独自のハンドラを持っている別のライブラリを使用して、あなたも試すことができます:
function myHandler(e) {
e.persist();
e.nativeEvent.stopImmediatePropagation();
e.stopPropagation();
}
私が理解したことから、event.persist
メソッドは、オブジェクトがすぐにReactのSyntheticEvent
プールに戻されるのを防ぎます。そのため、Reactに渡されたevent
は実際に到達するまで存在しません!これは、Reactが最初にSyntheticEvent
ハンドラーの親をチェックダウンすることによって(特に親にコールバックがあった場合)内部で物事を処理する方法のために、孫で発生します。
persist
などのイベントを作成し続けるためにかなりのメモリを作成するものでonMouseMove
を呼び出していない限り(そしておばあちゃんのCookiesのようなCookie Clickerゲームのようなものを作成していない限り)、完全に問題ないはずです!
また、GitHubをときどき読んで、今後のReactのバージョンに目を光らせておく必要がありますmayコンパイラ/トランスパイラーで折りたたみReactコードを作成します。
これを行うための新しい方法ははるかに簡単であり、時間を節約できます!イベントを元のクリックハンドラーに渡し、preventDefault();
を呼び出します。
clickHandler(e){
e.preventDefault();
//Your functionality here
}
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;
}
}
イベントのターゲットを確認することにより、イベントのバブリングを回避できます。
たとえば、クリックイベントのハンドラがあるdiv要素にネストされた入力があり、それを処理したくない場合、入力がクリックされたときに、ハンドラにevent.target
を渡してチェックするだけです。ハンドラは、ターゲットのプロパティに基づいて実行する必要があります。
たとえば、if (target.localName === "input") { return}
を確認できます。
それは、ハンドラーの実行を「回避」する方法です