React学习笔记(一)
<h4 id="组件化思想">组件化思想</h4><h5 id="组件">组件</h5>
<p>组件是构建 <code>React </code>应用的独立、可复用的代码块。它接收输入(称为 <code>props</code>),并返回描述<code>UI</code>的 <code>React</code> 元素。</p>
<h5 id="函数组件-vs-类组件">函数组件 vs 类组件</h5>
<ul>
<li>函数组件:一个接受输入,并输出<code>JSX</code>的函数。</li>
<li>类组件:使用<code>class</code>定义,并继承<code>React.Component</code>的类,必须包含一个<code>render()</code>方法。</li>
</ul>
<h5 id="为什么函数组件成为主流">为什么函数组件成为主流</h5>
<p>1、代码简洁:函数组件的语法更简单,没有<code>this</code>绑定问题。</p>
<p>2、Hooks的引入:引入Hooks后,函数组件也能拥有状态和生命周期等能力。</p>
<h5 id="受控组件-vs-非受控组件">受控组件 vs 非受控组件</h5>
<ul>
<li>受控组件:表单数据由<code>React</code>组件管理的组件。表单元素(<code>input</code>、<code>textarea</code>等)的值由<code>state</code>控制,并通过<code>onChange</code>事件来更新。</li>
<li>非受控组件:表单数据由DOM本身进行管理,可以使用<code>ref</code>从DOM节点中获取表单值。</li>
</ul>
<h4 id="状态和属性">状态和属性</h4>
<p><code>state</code>(状态)</p>
<ul>
<li>组件内部管理的数据,状态改变会触发组件的重新渲染。</li>
<li>如何更新:
<ul>
<li>类组件:使用<code>this.setState()</code></li>
<li>函数组件:使用<code>useState</code> Hook 返回更新函数</li>
<li>状态的更新是异步的,React会对同一个事件处理函数中的多个状态更新进行批处理</li>
<li>状态不可变,每次状态更新都会产生新的状态对象,直接修改状态不会重渲染</li>
</ul>
</li>
</ul>
<p><code>props</code>(属性)</p>
<ul>
<li>从组件外部传入的数据,类似函数的参数,只读,不能修改。</li>
<li>实现父组件向子组件通信(传递数据、回调函数等)</li>
</ul>
<h4 id="hooks"><strong>Hooks</strong></h4>
<h5 id="1usestate">1、<code>useState</code></h5>
<ul>
<li>作用:在函数组件中添加内部状态</li>
<li>语法:<code>const = useState(初始值)</code></li>
<li>关键点:初始值可以是一个值,也可以是一个函数。调用<code>setState</code>会替换状态对象</li>
</ul>
<h5 id="2useeffect">2、<code>useEffect</code></h5>
<ul>
<li>作用:在函数组件中执行副作用操作(数据获取,订阅,手动修改DOM等一些异步操作)</li>
<li>执行时机:默认情况下,在每次渲染后(包括首次渲染)都会执行。</li>
<li>依赖数组(第二个参数)的控制:
<ul>
<li>不提供依赖数组(<code>null</code>):每次渲染后都执行</li>
<li>依赖数组为空(<code>[]</code>):仅在组件挂载后执行一次(类似于<code>componentDidMount</code>)</li>
<li>依赖数组有值(<code></code>):在组件挂载后以及<code>dep1</code>或<code>dep2</code>发生改变时执行</li>
</ul>
</li>
<li>清除效应:如果<code>useEffect</code>的回调函数返回一个函数,这个函数会在组件卸载前和执行下一个副作用之前被调用,可以用于清理(取消订阅、清除定时器等)</li>
</ul>
<h5 id="3usecontext">3、<code>useContext</code></h5>
<ul>
<li>作用:接受一个Context对象(由<code>React.createContext()</code>创建)并返回该Context的当前值</li>
<li>实现与后代组件单向通信</li>
</ul>
<h5 id="4usecallback和usememo">4、<code>useCallback</code>和<code>useMemo</code></h5>
<ul>
<li><code>useCallback</code>:缓存函数本身,用于优化性能。
<ul>
<li>在进行重新渲染时,
<ul>
<li>如果依赖项没有发生变化,返回的是相同的函数,从而跳过重新渲染。</li>
<li>当依赖项改变时,会更新函数,并重新渲染。</li>
</ul>
</li>
</ul>
</li>
<li><code>useMemo</code>:缓存计算结果,用于优化性能
<ul>
<li>避免每次重新渲染时都进行高开销的计算任务</li>
<li>仅在依赖项改变时重新计算。</li>
</ul>
</li>
</ul>
<blockquote>
<p>在<code>JS</code>中每次运行<code>function(){}</code>和<code>()=>{}</code>都会生成新的函数对象。</p>
<p>父组件中定义了一个回调函数,子组件中调用了这个函数。当父组件状态改变时,会重渲染父组件,父组件中子组件也会重渲染,其中父组件重新生成了一个新的函数对象(虽然它的功能不变,但函数的引用变了,是一个新的对象),传入子组件的回调函数变了,所以子组件也要重新生成。</p>
<p>如果使用<code>useCallback</code>缓存该回调函数,只要依赖数组中的元素不变,当父组件重渲染时,它会返回缓存好的函数对象,而不是生成一个新的函数对象,传入子组件的回调函数不变,子组件跳过重新渲染。</p>
</blockquote>
<h5 id="5useref">5、<code>useRef</code></h5>
<ul>
<li>访问DOM元素</li>
<li>存储一个可变的值
<ul>
<li>ref的current属性可以在组件的整个生命周期内持久存在,而且改变它不会触发组件重新渲染,可以用来存储定时器ID,上一次属性或状态等。</li>
</ul>
</li>
</ul>
<h4 id="生命周期和hooks">生命周期和Hooks</h4>
<ul>
<li>
<p><code>componentDidMount</code>:组件挂载后回调</p>
<ul>
<li>使用 <code>useEffect</code> 并提供一个<strong>空依赖数组 <code>[]</code></strong>。</li>
</ul>
</li>
<li>
<p><code>componentDidUpdate</code>:组件状态更新时回调</p>
<ul>
<li>使用 <code>useEffect</code> 并<strong>不提供依赖数组</strong>或提供一个<strong>非空的依赖数组</strong>
<ul>
<li>使用 <code>useRef</code> 来保存一个在组件生命周期内持久存在的值(<code>isMounted</code>),它不会触发重渲染。</li>
<li>首次渲染时,<code>isMounted.current</code> 为 <code>false</code>,将其设为 <code>true</code> 但不执行更新逻辑。</li>
<li>后续渲染时,<code>isMounted.current</code> 为 <code>true</code>,执行更新逻辑。</li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>componentWillUnmount</code> :组件卸载之前回调</p>
<ul>
<li>在 <code>useEffect</code> 中<strong>返回一个清理函数</strong>并提供一个<strong>空依赖数组</strong>。</li>
</ul>
</li>
</ul>
<h4 id="虚拟dom">虚拟DOM</h4>
<p>一个轻量级的<code>Javascript</code>对象,是真实DOM的抽象,当组件状态改变时,React会先在虚拟DOM上进行比较计算,而不是直接操作DOM。</p>
<ul>
<li>
<p>工作流程:</p>
<ol>
<li>当状态改变时,会创建一个新的虚拟DOM树。</li>
<li>使用<code>Diffing</code>算法比较新旧两个虚拟DOM树,找出需要更新的最小部分</li>
<li>将计算出来的差异批量地应用到真实DOM上</li>
</ol>
</li>
<li>
<p>减少对真实DOM树的操作,极大提高性能。开发者无需关心如何高效地更新<code>UI</code>,只需要关心数据状态。</p>
</li>
</ul><br><br>
来源:https://www.cnblogs.com/ldh-blog/p/19117354
頁:
[1]