本篇內(nèi)容主要講解“React源碼中怎么實現(xiàn)受控組件”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“React源碼中怎么實現(xiàn)受控組件”吧!
創(chuàng)新互聯(lián)堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站建設(shè)、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的安多網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
在React中一個簡單的受控組件如下:
function App() { const [num, updateNum] = React.useState(0); const onChange = ({target: {value}}) => { updateNum(value); } return ( ) }
在onChange中會更新num,num作為value prop傳遞給,達(dá)到value受控的目的。
如果讓你來設(shè)計,你會怎么做?
我相信大部分同學(xué)第一個想法是:將value prop與其他attribute prop一樣處理就行。
我們知道React內(nèi)部運行有3個階段:
schedule 調(diào)度更新階段
render 進(jìn)行diff算法的階段
commit 進(jìn)行DOM操作的階段
假設(shè)我們要在onChange中觸發(fā)更新改變className,只需要在render階段記錄要改變的className,在commit階段執(zhí)行對應(yīng)的addClass DOM操作。
同樣的,如果我們要在onChange中觸發(fā)更新改變value,只需要在render階段記錄要改變的value,在commit階段執(zhí)行對應(yīng)的inputDOM.setAttribute('value', value)操作。
這樣邏輯非常通順。那么事實上呢?
直接改變value的問題
className只是inputDOM上的一個普通屬性。而value則涉及到輸入框光標(biāo)的位置。
如果我們直接修改value,那么屬性改變后input的光標(biāo)輸入位置也會丟失,光標(biāo)會跳到輸入框的最后。
想想我們將1234修改為12534。
1234 --> 12534
需要先將光標(biāo)位置移動到2之后,再輸入5。
如果setAttribute('value', '12534'),那么光標(biāo)不會保持在5后面而是跳到4后面。
那么React如何解決這個問題呢?
用非受控的形式實現(xiàn)受控組件
你沒有看錯,React用非受控形式實現(xiàn)了受控組件的邏輯。
簡單的說,不同于className在commit階段受控更新,value則完全是非受控的形式,只在必要的時候受控更新。
因為一旦更新value,那么光標(biāo)位置就會丟失。
我們稍微修改下Demo,input為受控組件,value始終為1:
function App() { const num = 1; return ( ) }
當(dāng)我們在源碼中打上斷點,輸入2后,實際上會先顯示12,再刪掉2。
只不過這個刪除的過程是同步的所以看起來輸入框內(nèi)始終只有1。
所以,不同于React其他組件props的更新會經(jīng)歷schedule - render - commit流程。
對于input、textarea、select,React有一條單獨的更新路徑,這條路徑觸發(fā)的更新被稱為discreteUpdate。
這條路徑的工作流程如下:
鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)
先以非受控的形式更新表單DOM
以同步的優(yōu)先級開啟一次更新
更新后的value在commit階段并不會像其他props一樣作用于DOM
調(diào)用restoreStateOfTarget方法,比較DOM的實際value(即步驟1中的非受控value)與步驟3中更新的value,如果相同則退出,如果不同則用步驟3的value更新DOM
什么情況下這2個value會相同呢?
我們正常的受控組件就是相同的情況:
function App() { const [num, updateNum] = React.useState(0); const onChange = ({target: {value}}) => { updateNum(value); } return ( ) }
什么情況下這2個value會不同呢?
上面的Demo中,雖然受控,但是沒有調(diào)用updateNum更新value的情況:
function App() { const num = 1; return ( ) }
在這種情況下,步驟1的非受控value變?yōu)榱?2,步驟3的受控value還是1,所以最終會用1再更新下DOM的value。
到此,相信大家對“React源碼中怎么實現(xiàn)受控組件”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!