React イベント システムの分析

不言
リリース: 2018-07-23 11:17:28
オリジナル
1490 人が閲覧しました

この記事で共有した内容は React イベント システムの分析に関するもので、必要な方は参考にしてください。

1 はじめに

React イベント システムには、合成イベントとネイティブ イベントの 2 種類があります。
React コンポーネントを作成する場合、合成イベントをバインドするのは簡単ですが、現時点では、1 つのコンポーネント内で別のコンポーネントの合成イベントをバインドする方法はありません。
混合 (合成イベントとネイティブ イベントの混合) イベントについて説明することに加えて、イベント バブリングもよく対処する必要があるものです。この記事では、React と組み合わせて紹介します。

2 番目のテキスト

1. React イベント システム

1-1. React は、Virtual DOM に基づいて SyntheticEvent (合成イベント) レイヤーを実装し、SyntheticEvent オブジェクトのインスタンスを受け取ります。バブリングメカニズムでは、stopPropagation() とPreventDefault() を使用してそれを中断できます。

1-2. すべてのイベントは自動的に最外層 (ドキュメント) にバインドされます。

2. 合成イベント バインディング メカニズム

React の下部には、合成イベントに対して行われる 2 つの主な処理があります: イベント委任と自動バインディング。

2-1. イベント委任
React イベントを使用する前に、そのイベント委任メカニズムについてよく理解しておく必要があります。イベント処理関数を実際のノードに直接バインドするのではなく、統合されたイベント リスナーを使用して、すべてのイベントを構造の最外層にバインドし、すべてのコンポーネント内にイベント リスニングおよび処理関数を保存します。コンポーネントがマウントまたはマウント解除されると、一部のオブジェクトがこの統合イベント リスナーに挿入または削除されます。イベントが発生すると、最初にこの統合イベント リスナーによって処理され、次に実際のイベント処理関数がマッピング内で検出されて呼び出されます。 。これにより、イベントの処理とリサイクルのメカニズムが簡素化され、効率が大幅に向上します。 2-2. 自動バインド

React コンポーネントでは、各メソッドのコンテキストはコンポーネントのインスタンスを指します。つまり、

これを現在のコンポーネントに自動的にバインドします
。また、React はこの参照をキャッシュして、CPU とメモリの最適化を実現します。 3. React でネイティブ イベントを使用する

ネイティブ イベントは React アーキテクチャでも使用できます。 React は完全なライフサイクル メソッドを提供します。コンポーネントがインストールされ、実際の DOM がブラウザーに存在すると、componentDidMount が呼び出されます。この時点で、ネイティブ イベントのバインドを完了できます。

しかし、React はネイティブ イベントを自動的に管理しないため、

コンポーネントをアンインストールするときは、ネイティブ イベントからログアウトする必要があります
4. 合成イベントとネイティブ イベントの混合

本で言及されています (ここではあまり紹介しません):

    合成イベントとネイティブ イベントを混合しないでください
  • 避けるために e.target の判断を使用します。
  • 重要な点は次の段落であり、これは今日私たちが解決に焦点を当てる問題でもあります:

バブリングを防ぐためにreactEvent.nativeEvent.stopPropagation() を使用することはできません。 React イベントのバブリングを防ぐ動作は、React 合成イベント システムでのみ使用でき、ネイティブ イベントのバブリングを防ぐ方法はありません。逆に、ネイティブ イベントのバブリング動作を防止すると、React 合成イベントの伝播を防ぐことができます。

5.React stopPropagation と stopImmediatePropagation

イベント バブリング メカニズム:


React イベント システムの分析
React を通じてバインドされたイベント、コールバック関数内のイベント オブジェクトは React によって合成された SyntheticEvent であり、ネイティブ DOM のイベントとは異なりますイベント 一つ。正確に言うと、React では e.nativeEvent がネイティブ DOM イベントのイベントになります。

React 合成イベントとネイティブ イベントの実行シーケンス図:


React イベント システムの分析
この図から、次の結論を引き出すことができます:

(1) React 合成イベントは、DOM イベントがドキュメントにバブルアップした場合にのみトリガーされます。 React の合成イベント オブジェクトの e.stopPropagation は、React でシミュレートされたイベントのバブリングを防ぐことができるだけで、実際の DOM イベントのバブリングを防ぐことはできません

(2) DOM イベントのバブリングを防止すると、合成イベントも防止できるからです。 DOMイベントのバブリングを防ぐとイベントがドキュメントに伝播されなくなります
(3)合成イベントとDOMイベントの両方がドキュメントにバインドされている場合、Reactの処理は合成イベントを先に入れることになるので、この場合、オブジェクトのネイティブ イベント stopImmediatePropagation が、ドキュメント DOM イベントのさらなるトリガーを防ぐことができます

React イベント システムの分析
stopImmediatePropagation: 同じ要素にバインドされた同じタイプのイベントのイベント リスニング関数が複数ある場合、そのタイプのイベントがトリガーされると、追加された順序に従って実行されます。リスニング関数の 1 つがevent.stopImmediatePropagation() メソッドを実行すると、残りのリスニング関数は実行されません

6.React によるバブリング防止の概要

(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,    });   }); 
 }
ログイン後にコピー

7.

7-1 イベント登録

イベント登録とは、ドキュメントノードで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. イベント実行

  • イベントがトリガーされるたびに、ルートノードのaddEventListenerで登録されたコールバック、イベント配信エントリ関数であるReactEventListener.dispatchEventメソッドが実行されます。この関数の主なビジネス ロジックは次のとおりです:

    • DOM イベントに基づいて React 合成イベントを構築します。

    • 作曲イベントをキューに入れます。

    • バッチキュー内のイベント (以前に処理されていないもの、先入れ先出しを含む)

    • イベントによってトリガーされた DOM と React コンポーネントを検索します

    • React コンポーネントから、 findParent メソッドを呼び出し、配列に格納されているすべての親コンポーネントを取得します。

    • このコンポーネントから最後の親コンポーネントまで、前のイベントストレージに従って、Reactイベント名+コンポーネントキーを使用して、対応するバインディングコールバックメソッドを見つけて実行します。詳細なプロセスは次のとおりです:

バブリング。 React 合成イベントの実際のバブリングではありませんが、ノード トラバーサルです。

3 つの追記

個人的には、stopImmediatePropagation は非常に便利だと思います。合成イベントが DOM ドキュメントに発生するのを防ぐ必要があります。その理由は次のとおりです。

1.合成事件本来就绑定在document上,完全可以获取这个document
2.stopImmediatePropagation可以阻止触发的document DOM上的事件,这十分有必要
3.不会阻止DOM 上的事件冒泡到document DOM
ログイン後にコピー
関連する推奨事項: でよく使用される 3 つの値転送メソッド。 Vue

React Eventイベント登録の実装

以上がReact イベント システムの分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート