ホームページ > 記事 > ウェブフロントエンド > React イベント システムの分析
この記事で共有した内容は React イベント システムの分析に関するもので、必要な方は参考にしてください。
React イベント システムには、合成イベントとネイティブ イベントの 2 種類があります。
React コンポーネントを作成する場合、合成イベントをバインドするのは簡単ですが、現時点では、1 つのコンポーネント内で別のコンポーネントの合成イベントをバインドする方法はありません。
混合 (合成イベントとネイティブ イベントの混合) イベントについて説明することに加えて、イベント バブリングもよく対処する必要があるものです。この記事では、React と組み合わせて紹介します。
1-1. React は、Virtual DOM に基づいて SyntheticEvent (合成イベント) レイヤーを実装し、SyntheticEvent オブジェクトのインスタンスを受け取ります。バブリングメカニズムでは、stopPropagation() とPreventDefault() を使用してそれを中断できます。
1-2. すべてのイベントは自動的に最外層 (ドキュメント) にバインドされます。
React の下部には、合成イベントに対して行われる 2 つの主な処理があります: イベント委任と自動バインディング。
2-1. イベント委任
React イベントを使用する前に、そのイベント委任メカニズムについてよく理解しておく必要があります。イベント処理関数を実際のノードに直接バインドするのではなく、統合されたイベント リスナーを使用して、すべてのイベントを構造の最外層にバインドし、すべてのコンポーネント内にイベント リスニングおよび処理関数を保存します。コンポーネントがマウントまたはマウント解除されると、一部のオブジェクトがこの統合イベント リスナーに挿入または削除されます。イベントが発生すると、最初にこの統合イベント リスナーによって処理され、次に実際のイベント処理関数がマッピング内で検出されて呼び出されます。 。これにより、イベントの処理とリサイクルのメカニズムが簡素化され、効率が大幅に向上します。 2-2. 自動バインド
これを現在のコンポーネントに自動的にバインドします
。また、React はこの参照をキャッシュして、CPU とメモリの最適化を実現します。 3. React でネイティブ イベントを使用する
コンポーネントをアンインストールするときは、ネイティブ イベントからログアウトする必要があります
。 4. 合成イベントとネイティブ イベントの混合
バブリングを防ぐためにreactEvent.nativeEvent.stopPropagation() を使用することはできません。 React イベントのバブリングを防ぐ動作は、React 合成イベント システムでのみ使用でき、ネイティブ イベントのバブリングを防ぐ方法はありません。逆に、ネイティブ イベントのバブリング動作を防止すると、React 合成イベントの伝播を防ぐことができます。
5.React stopPropagation と stopImmediatePropagation
React を通じてバインドされたイベント、コールバック関数内のイベント オブジェクトは React によって合成された SyntheticEvent であり、ネイティブ DOM のイベントとは異なりますイベント 一つ。正確に言うと、React では e.nativeEvent がネイティブ DOM イベントのイベントになります。
この図から、次の結論を引き出すことができます:
(2) DOM イベントのバブリングを防止すると、合成イベントも防止できるからです。 DOMイベントのバブリングを防ぐとイベントがドキュメントに伝播されなくなります
(3)合成イベントとDOMイベントの両方がドキュメントにバインドされている場合、Reactの処理は合成イベントを先に入れることになるので、この場合、オブジェクトのネイティブ イベント stopImmediatePropagation が、ドキュメント DOM イベントのさらなるトリガーを防ぐことができます
stopImmediatePropagation: 同じ要素にバインドされた同じタイプのイベントのイベント リスニング関数が複数ある場合、そのタイプのイベントがトリガーされると、追加された順序に従って実行されます。リスニング関数の 1 つがevent.stopImmediatePropagation() メソッドを実行すると、残りのリスニング関数は実行されません
(1) 合成イベント間のバブリングを防止するには、 e.stopPropagation(); を使用します。
(2) 合成イベントと最も外側のドキュメント上のイベント間のバブリングを防止するには、 e.nativeEvent.stopImmediatePropagation( );
(3) 一番外側のドキュメント以外の合成イベントとネイティブイベントのバブリングを防ぐ コードは以下の通りです:
componentDidMount() { document.body.addEventListener('click', e => { if (e.target && e.target.matches('p.code')) { return; } this.setState({ active: false, }); }); }
イベント登録とは、ドキュメントノードでReactイベントをDOMネイティブイベントに変換し、コールバックを登録することです。
// enqueuePutListener 负责事件注册。 // inst:注册事件的 React 组件实例 // registrationName:React 事件,如:onClick、onChange // listener:和事件绑定的 React 回调方法,如:handleClick、handleChange // transaction:React 事务流,不懂没关系,不太影响对事件系统的理解 function enqueuePutListener(inst, registrationName, listener, transaction) { ... ... // doc 为找到的 document 节点 var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument; // 事件注册 listenTo(registrationName, doc); // 事件存储,之后会讲到,即存储事件回调方法 transaction.getReactMountReady().enqueue(putListener, { inst: inst, registrationName: registrationName, listener: listener }); }イベント登録の具体的なコードと、DOM ネイティブ イベントをドキュメントにバインドする方法を見てみましょう。
// 事件注册 // registrationName:React 事件名,如:onClick、onChange // contentDocumentHandle:要将事件绑定到的 DOM 节点 listenTo: function (registrationName, contentDocumentHandle) { // document var mountAt = contentDocumentHandle; // React 事件和绑定在根节点的 topEvent 的转化关系,如:onClick -> topClick var dependencies = EventPluginRegistry.registrationNameDependencies[registrationName]; for (var i = 0; i イベントをバブリングフェーズにバインドするための具体的なコードを見てみましょう: <p></p><pre class="brush:php;toolbar:false">// 三个参数为 topEvent、原生 DOM Event、Document(挂载节点) trapBubbledEvent: function (topLevelType, handlerBaseName, element) { if (!element) { return null; } return EventListener.listen(element, handlerBaseName, ReactEventListener.dispatchEvent.bind(null, topLevelType)); } // 三个参数为 Document(挂载节点)、原生 DOM Event、事件绑定函数 listen: function listen(target, eventType, callback) { // 去除浏览器兼容部分,留下核心后 target.addEventListener(eventType, callback, false); // 返回一个解绑的函数 return { remove: function remove() { target.removeEventListener(eventType, callback, false); } } }listen メソッドで、おなじみの addEventListener ネイティブ イベント登録メソッドをついに発見しました。ドキュメント ノードのみがこのメソッドを呼び出すため、ドキュメント ノードのみが DOM イベントを持ちます。これにより、DOM イベント ロジックが大幅に簡素化され、メモリが節約されます。 7-2. イベントの保存
イベントを登録したら、イベントにバインドされたコールバック関数を保存する必要があります。このようにして、イベントがトリガーされた後にのみ、トリガーする対応するコールバックを見つけることができます。最初のコードでは、イベント コールバックを保存するために putListener メソッドが使用されていることがわかりました。
// inst:注册事件的 React 组件实例 // registrationName:React 事件,如:onClick、onChange // listener:和事件绑定的 React 回调方法,如:handleClick、handleChange putListener: function (inst, registrationName, listener) { // 核心代码如下 // 生成每个组件实例唯一的标识符 key var key = getDictionaryKey(inst); // 获取某种 React 事件在回调存储银行中的对象 var bankForRegistrationName = listenerBank[registrationName] || (listenerBank[registrationName] = {}); bankForRegistrationName[key] = listener; }7-3. イベント実行
1.合成事件本来就绑定在document上,完全可以获取这个document 2.stopImmediatePropagation可以阻止触发的document DOM上的事件,这十分有必要 3.不会阻止DOM 上的事件冒泡到document DOM関連する推奨事項: でよく使用される 3 つの値転送メソッド。 Vue
以上がReact イベント システムの分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。