<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>React 事件机制 on Last Stand</title><link>https://amatsuzero.github.io/LastStand/tags/react-%E4%BA%8B%E4%BB%B6%E6%9C%BA%E5%88%B6/</link><description>Recent content in React 事件机制 on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Fri, 14 Mar 2025 00:00:00 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/tags/react-%E4%BA%8B%E4%BB%B6%E6%9C%BA%E5%88%B6/index.xml" rel="self" type="application/rss+xml"/><item><title>react 事件机制</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/react/react-009/</link><pubDate>Tue, 17 Dec 2024 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/react/react-009/</guid><description>&lt;h2 id="一-前言"&gt;一 前言&lt;/h2&gt;
&lt;p&gt;我们来一起探讨一下&lt;code&gt;React&lt;/code&gt;事件原理，这篇文章，我尽量用通俗简洁的方式，把&lt;code&gt;React&lt;/code&gt;事件系统讲的明明白白。&lt;/p&gt;
&lt;p&gt;我们讲的&lt;code&gt;react&lt;/code&gt;版本是&lt;code&gt;16.13.1&lt;/code&gt; , &lt;code&gt;v17&lt;/code&gt;之后&lt;code&gt;react&lt;/code&gt;对于事件系统会有相关的改版，文章后半部分会提及。&lt;/p&gt;
&lt;p&gt;老规矩，在正式讲解&lt;code&gt;react&lt;/code&gt;之前，我们先想想这几个问题(&lt;strong&gt;如果我是面试官，你会怎么回答?&lt;/strong&gt;)：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我们写的事件是绑定在&lt;code&gt;dom&lt;/code&gt;上么，如果不是绑定在哪里？&lt;/li&gt;
&lt;li&gt;为什么我们的事件不能绑定给组件？&lt;/li&gt;
&lt;li&gt;为什么我们的事件手动绑定&lt;code&gt;this&lt;/code&gt;(不是箭头函数的情况)&lt;/li&gt;
&lt;li&gt;为什么不能用 &lt;code&gt;return false&lt;/code&gt; 来阻止事件的默认行为？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;react&lt;/code&gt;怎么通过&lt;code&gt;dom&lt;/code&gt;元素，找到与之对应的 &lt;code&gt;fiber&lt;/code&gt;对象的？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;onClick&lt;/code&gt;是在冒泡阶段绑定的？ 那么&lt;code&gt;onClickCapture&lt;/code&gt;就是在事件捕获阶段绑定的吗？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/react/react-009/image-01.webp"&gt;&lt;/p&gt;
&lt;h2 id="必要的知识概念"&gt;必要的知识概念&lt;/h2&gt;
&lt;p&gt;在弄清楚&lt;code&gt;react&lt;/code&gt;事件之前，有几个概念我们必须弄清楚，因为只有弄明白这几个概念，在事件触发阶段，我们才能更好的理解&lt;code&gt;react&lt;/code&gt;处理事件本质。&lt;/p&gt;
&lt;h3 id="我们写在jsx事件终将变成什么"&gt;我们写在JSX事件终将变成什么？&lt;/h3&gt;
&lt;p&gt;我们先写一段含有点击事件的&lt;code&gt;react JSX&lt;/code&gt;语法，看一下它最终会变成什么样子？&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;handerClick&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;) =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;div&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;button&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onClick&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{ &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;handerClick&lt;/span&gt; } &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;按钮点击&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/button&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/div&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;经过&lt;code&gt;babel&lt;/code&gt;转换成&lt;code&gt;React.createElement&lt;/code&gt;形式，如下：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/react/react-009/image-02.webp"&gt;&lt;/p&gt;
&lt;p&gt;最终转成&lt;code&gt;fiber&lt;/code&gt;对象形式如下：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/react/react-009/image-03.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fiber&lt;/code&gt;对象上的&lt;code&gt;memoizedProps&lt;/code&gt; 和 &lt;code&gt;pendingProps&lt;/code&gt;保存了我们的事件。&lt;/p&gt;
&lt;h3 id="什么是合成事件"&gt;什么是合成事件？&lt;/h3&gt;
&lt;p&gt;通过上一步我们看到了，我们声明事件保存的位置。但是事件有没有被真正的注册呢？我们接下来看一下：&lt;/p&gt;
&lt;p&gt;我们看一下当前这个元素&lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;上有没有绑定这个事件监听器呢？&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/react/react-009/image-04.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;button上绑定的事件&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我们可以看到 ，&lt;code&gt;button&lt;/code&gt;上绑定了两个事件，一个是&lt;code&gt;document&lt;/code&gt;上的事件监听器，另外一个是&lt;code&gt;button&lt;/code&gt;，但是事件处理函数&lt;code&gt;handle&lt;/code&gt;，并不是我们的&lt;code&gt;handerClick&lt;/code&gt;事件，而是&lt;code&gt;noop&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;noop&lt;/code&gt;是什么呢？我们接着来看。&lt;/p&gt;
&lt;p&gt;原来&lt;code&gt;noop&lt;/code&gt;就指向一个空函数。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/react/react-009/image-05.webp"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;然后我们看&lt;code&gt;document&lt;/code&gt;绑定的事件&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/react/react-009/image-06.webp"&gt;&lt;/p&gt;
&lt;p&gt;可以看到&lt;code&gt;click&lt;/code&gt;事件被绑定在&lt;code&gt;document&lt;/code&gt;上了。&lt;/p&gt;
&lt;p&gt;接下来我们再搞搞事情😂😂😂，在&lt;code&gt;demo&lt;/code&gt;项目中加上一个&lt;code&gt;input&lt;/code&gt;输入框，并绑定一个&lt;code&gt;onChange&lt;/code&gt;事件。睁大眼睛看看接下来会发生什么？&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Index&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;React&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Component&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;componentDidMount&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;handerClick&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;) =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;handerChange&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;) =&amp;gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;value&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;render&lt;/span&gt;(){
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;div&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;style&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{{ &lt;span style="color:#a6e22e"&gt;marginTop&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#39;50px&amp;#39;&lt;/span&gt; }} &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;button&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onClick&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{ &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;handerClick&lt;/span&gt; } &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;按钮点击&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/button&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;input&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;placeholder&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;请输入内容&amp;#34;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;onChange&lt;/span&gt;&lt;span style="color:#f92672"&gt;=&lt;/span&gt;{ &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;handerChange&lt;/span&gt; } &lt;span style="color:#f92672"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#960050;background-color:#1e0010"&gt;/div&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;我们先看一下&lt;code&gt;input dom&lt;/code&gt;元素上绑定的事件&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>