Der Inhalt, der in diesem Artikel mit Ihnen geteilt wird, befasst sich mit der Analyse des React-Ereignissystems. Freunde in Not können sich darauf beziehen.
Es gibt zwei Arten von React-Ereignissystemen: synthetische Ereignisse und native Ereignisse.
Beim Schreiben von React-Komponenten ist es für uns einfach, ein synthetisches Ereignis zu binden, aber es gibt keine Möglichkeit, das synthetische Ereignis einer anderen Komponente in einer Komponente zu binden. Zu diesem Zeitpunkt sind native Ereignisse praktisch.
Neben der Diskussion über gemischte Ereignisse (Mischung von synthetischen Ereignissen und nativen Ereignissen) müssen wir uns auch häufig mit dem Ereignis-Bubbling befassen. In diesem Artikel wird es in Verbindung mit React vorgestellt.
1-1. React implementiert eine SyntheticEvent-Ebene (synthetisches Ereignis), die auf Virtual DOM basiert, dem von uns definierten Ereignishandler eines SyntheticEvent-Objekts wird empfangen, und der Event-Bubbling-Mechanismus wird ebenfalls unterstützt. Wir können stopPropagation() und präventDefault() verwenden, um es zu unterbrechen.
1-2. Alle Ereignisse werden automatisch an die äußerste Ebene (Dokument) gebunden.
Am Ende von React werden zwei Hauptfunktionen für synthetische Ereignisse durchgeführt: Ereignisdelegation und automatische Bindung.
2-1. Ereignisdelegierung Bevor Sie
React Events verwenden, müssen Sie mit dem Ereignisdelegierungsmechanismus vertraut sein. Es bindet die Ereignisverarbeitungsfunktion nicht direkt an den realen Knoten, sondern bindet alle Ereignisse an die äußerste Schicht der Struktur und verwendet dazu einen einheitlichen Ereignis-Listener . Dieser Ereignis-Listener wird zum Speichern aller Ereignis-Listener verwaltet und Handler innerhalb der Komponente. Wenn eine Komponente gemountet oder nicht gemountet wird, werden einige Objekte einfach in diesen einheitlichen Ereignis-Listener eingefügt oder gelöscht. Wenn ein Ereignis auftritt, wird es zuerst von diesem einheitlichen Ereignis-Listener verarbeitet, und dann wird die eigentliche Ereignisverarbeitungsfunktion in der Zuordnung gefunden und aufgerufen . Dies vereinfacht den Ereignisverarbeitungs- und Recyclingmechanismus und verbessert die Effizienz erheblich.
2-2. Automatische Bindung
In einer React-Komponente zeigt der Kontext jeder Methode auf die Instanz der Komponente, d. h. bindet diese automatisch an die aktuelle Komponente . Und React speichert diese Referenz auch zwischen, um eine CPU- und Speicheroptimierung zu erreichen.
Native Ereignisse können auch unter der React-Architektur verwendet werden. React bietet eine vollständige Lebenszyklusmethode, die aufgerufen wird, nachdem die Komponente installiert wurde und das echte DOM im Browser vorhanden ist. Zu diesem Zeitpunkt können wir die Bindung nativer Ereignisse abschließen.
Aber React verwaltet native Ereignisse nicht automatisch, daher müssen Sie sich bei der Deinstallation der Komponente von nativen Ereignissen abmelden .
Es wird im Buch erwähnt (hier nicht zu viel Einführung):
Nicht mischen synthetische Ereignisse mit Mischung nativer Ereignisse
Vermeiden Sie es durch e.target-Beurteilung
Der entscheidende Punkt ist der folgende Absatz, der auch der ist Problem, auf dessen Lösung wir uns heute konzentrieren möchten:
Die Verwendung von „reactEvent.nativeEvent.stopPropagation()“ zur Verhinderung von Blasenbildung wird nicht funktionieren. Das Verhalten, das das Sprudeln von React-Ereignissen verhindert, kann nur im synthetischen React-Ereignissystem verwendet werden, und es gibt keine Möglichkeit, das Sprudeln nativer Ereignisse zu verhindern. Im Gegenteil, die Verhinderung des Blasenverhaltens in nativen Ereignissen kann die Ausbreitung synthetischer React-Ereignisse verhindern.
Ereignisblasenmechanismus:
Ereignisse, die durch React gebunden sind, in ihren Rückruffunktionen Das Ereignisobjekt ist ein von React synthetisiertes SyntheticEvent, das nicht dasselbe ist wie das native DOM-Ereignis. Genauer gesagt ist e.nativeEvent in React das Ereignis des nativen DOM-Ereignisses.
Sequenzdiagramm für synthetische Ereignisse und native Ereignisse ausführen:
Aus dem Diagramm können wir die folgenden Schlussfolgerungen ziehen:
(1) Das synthetische Ereignis von DOM React wird nur ausgelöst, wenn das Ereignis zum Dokument sprudelt. Daher kann die e.stopPropagation des synthetischen React-Ereignisobjekts nur verhindern, dass das simulierte React-Ereignis sprudelt, nicht jedoch, dass das echte DOM-Ereignis sprudelt
( 2) Das Verhindern des Bubblings von DOM-Ereignissen kann auch synthetische Ereignisse verhindern. Der Grund dafür ist, dass das Verhindern des Bubblings von DOM-Ereignissen die Weitergabe von Ereignissen an das Dokument verhindert
(3) Wenn sowohl synthetische Ereignisse als auch DOM-Ereignisse an das Dokument gebunden sind, erfolgt die React-Verarbeitung Das synthetische Ereignis sollte zuerst eingefügt werden, damit es zuerst ausgelöst wird. In diesem Fall kann stopImmediatePropagation des nativen Ereignisobjekts ein weiteres Auslösen des Dokument-DOM-Ereignisses verhindern
stopImmediatePropagation: Wenn mehrere Ereignisüberwachungsfunktionen desselben Ereignistyps an dasselbe Element gebunden sind, werden Ereignisse dieses Typs beim Auslösen in der Reihenfolge ausgeführt, in der sie hinzugefügt wurden. Wenn eine der Abhörfunktionen die Methode event.stopImmediatePropagation() ausführt, werden die übrigen Abhörfunktionen nicht ausgeführt
(1) Um Blasenbildung zwischen synthetischen Ereignissen zu verhindern, verwenden Sie
(2), um zu verhindern, dass synthetische Ereignisse mit dem äußersten Dokument verbunden werden Um Sprudeln zwischen Ereignissen zu verhindern, verwenden Sie e.nativeEvent.stopImmediatePropagation();
(3), um Sprudeln zwischen synthetischen Ereignissen und nativen Ereignissen mit Ausnahme des äußersten Dokuments zu verhindern. Dies kann durch die Beurteilung von e.target vermieden werden :
componentDidMount() { document.body.addEventListener('click', e => { if (e.target && e.target.matches('p.code')) { return; } this.setState({ active: false, }); }); }
7-1 Ereignisregistrierung
Die Ereignisregistrierung besteht darin, React-Ereignisse in DOM-native Ereignisse am Dokumentknoten umzuwandeln und Rückrufe zu registrieren.
// 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 }); }
Schauen wir uns den spezifischen Code der Ereignisregistrierung an und wie man native DOM-Ereignisse an das Dokument bindet.
// 事件注册 // 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>Sehen Sie sich den spezifischen Code zum Binden von Ereignissen an die Bubbling-Phase an: </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); } } }
In der Listen-Methode haben wir endlich die bekannte native Ereignisregistrierungsmethode addEventListener entdeckt. Nur der Dokumentknoten ruft diese Methode auf, daher verfügt nur der Dokumentknoten über DOM-Ereignisse. Dies vereinfacht die DOM-Ereignislogik erheblich und spart Speicher.
7-2. Ereignisspeicherung
Nachdem das Ereignis registriert wurde, muss die an das Ereignis gebundene Rückruffunktion gespeichert werden. Auf diese Weise können wir erst nach dem Auslösen des Ereignisses den entsprechenden auszulösenden Rückruf finden. Im ersten Code haben wir gesehen, dass die putListener-Methode zum Speichern von Ereignisrückrufen verwendet wird.
// 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. Ereignisausführung
Jedes Mal, wenn ein Ereignis ausgelöst wird, wird der von addEventListener auf dem Stammknoten registrierte Rückruf ausgeführt, der der ReactEventListener ist. „dispatchEvent“-Methode, die Ereignisverteilungseintragsfunktion. Die Hauptgeschäftslogik dieser Funktion lautet wie folgt:
Konstruieren Sie synthetische React-Ereignisse basierend auf DOM-Ereignissen.
Stellen Sie das Kompositionsereignis in die Warteschlange.
Ereignisse in der Batch-Warteschlange (einschließlich solcher, die zuvor noch nicht verarbeitet wurden, wer zuerst kommt, mahlt zuerst)
Suchen Sie das DOM und reagieren Sie Durch das Ereignis ausgelöste Komponente
Rufen Sie von dieser Reaktionskomponente aus die Methode findParent auf, um alle übergeordneten Komponenten zu durchlaufen und sie in einem Array zu speichern.
Von dieser Komponente bis zur letzten übergeordneten Komponente verwenden Sie gemäß dem vorherigen Ereignisspeicher den Namen des React-Ereignisses + den Komponentenschlüssel, um die entsprechende Bindungsrückrufmethode zu finden und auszuführen. Der detaillierte Prozess ist:
Das Sprudeln von synthetischen React-Ereignissen ist nicht wirklich Sprudeln, sondern das Durchqueren von Knoten.
Ich persönlich halte stopImmediatePropagation für sehr nützlich. Es ist notwendig, zu verhindern, dass synthetische Ereignisse in das DOM-Dokument gelangen. Der Grund ist:
1.合成事件本来就绑定在document上,完全可以获取这个document 2.stopImmediatePropagation可以阻止触发的document DOM上的事件,这十分有必要 3.不会阻止DOM 上的事件冒泡到document DOM
Verwandte Empfehlungen :
Drei häufig verwendete Wertübergabemethoden in Vue
React Event-Ereignisregistrierungsimplementierung
Das obige ist der detaillierte Inhalt vonEine Analyse des React-Ereignissystems. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!