日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
React源碼中如何實(shí)現(xiàn)受控組件

今天我們站在框架開發(fā)者的角度來聊聊如何實(shí)現(xiàn)受控組件。

田家庵網(wǎng)站建設(shè)公司成都創(chuàng)新互聯(lián),田家庵網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為田家庵上1000+提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)營銷網(wǎng)站建設(shè)要多少錢,請找那個(gè)售后服務(wù)好的田家庵做網(wǎng)站的公司定做!

在React中一個(gè)簡單的受控組件如下:

 
 
 
 
  1. function App() { 
  2.   const [num, updateNum] = React.useState(0); 
  3.    
  4.   const onChange = ({target: {value}}) => { 
  5.     updateNum(value); 
  6.   } 
  7.  
  8.   return ( 
  9.      
  10.   ) 

在onChange中會(huì)更新num,num作為value prop傳遞給,達(dá)到value受控的目的。

如果讓你來設(shè)計(jì),你會(huì)怎么做?

我相信大部分同學(xué)第一個(gè)想法是:將value prop與其他attribute prop一樣處理就行。

我們知道React內(nèi)部運(yùn)行有3個(gè)階段:

  • schedule 調(diào)度更新階段
  • render 進(jìn)行diff算法的階段
  • commit 進(jìn)行DOM操作的階段

假設(shè)我們要在onChange中觸發(fā)更新改變className,只需要在render階段記錄要改變的className,在commit階段執(zhí)行對(duì)應(yīng)的addClass DOM操作。

同樣的,如果我們要在onChange中觸發(fā)更新改變value,只需要在render階段記錄要改變的value,在commit階段執(zhí)行對(duì)應(yīng)的inputDOM.setAttribute('value', value)操作。

這樣邏輯非常通順。那么事實(shí)上呢?

直接改變value的問題
className只是inputDOM上的一個(gè)普通屬性。而value則涉及到輸入框光標(biāo)的位置。

如果我們直接修改value,那么屬性改變后input的光標(biāo)輸入位置也會(huì)丟失,光標(biāo)會(huì)跳到輸入框的最后。

想想我們將1234修改為12534。

 
 
 
 
  1. 1234 --> 12534 

需要先將光標(biāo)位置移動(dòng)到2之后,再輸入5。

如果setAttribute('value', '12534'),那么光標(biāo)不會(huì)保持在5后面而是跳到4后面。

那么React如何解決這個(gè)問題呢?

用非受控的形式實(shí)現(xiàn)受控組件

你沒有看錯(cuò),React用非受控形式實(shí)現(xiàn)了受控組件的邏輯。

簡單的說,不同于className在commit階段受控更新,value則完全是非受控的形式,只在必要的時(shí)候受控更新。

因?yàn)橐坏└聉alue,那么光標(biāo)位置就會(huì)丟失。

我們稍微修改下Demo,input為受控組件,value始終為1:

 
 
 
 
  1. function App() { 
  2.   const num = 1; 
  3.  
  4.   return ( 
  5.      
  6.   ) 

當(dāng)我們在源碼中打上斷點(diǎn),輸入2后,實(shí)際上會(huì)先顯示12,再刪掉2。

只不過這個(gè)刪除的過程是同步的所以看起來輸入框內(nèi)始終只有1。

所以,不同于React其他組件props的更新會(huì)經(jīng)歷schedule - render - commit流程。

對(duì)于input、textarea、select,React有一條單獨(dú)的更新路徑,這條路徑觸發(fā)的更新被稱為discreteUpdate。

這條路徑的工作流程如下:

  1. 先以非受控的形式更新表單DOM
  2. 以同步的優(yōu)先級(jí)開啟一次更新
  3. 更新后的value在commit階段并不會(huì)像其他props一樣作用于DOM
  4. 調(diào)用restoreStateOfTarget方法,比較DOM的實(shí)際value(即步驟1中的非受控value)與步驟3中更新的value,如果相同則退出,如果不同則用步驟3的value更新DOM

什么情況下這2個(gè)value會(huì)相同呢?

我們正常的受控組件就是相同的情況:

 
 
 
 
  1. function App() { 
  2.   const [num, updateNum] = React.useState(0); 
  3.    
  4.   const onChange = ({target: {value}}) => { 
  5.     updateNum(value); 
  6.   } 
  7.  
  8.   return ( 
  9.      
  10.   ) 

什么情況下這2個(gè)value會(huì)不同呢?

上面的Demo中,雖然受控,但是沒有調(diào)用updateNum更新value的情況:

 
 
 
 
  1. function App() { 
  2.   const num = 1; 
  3.  
  4.   return ( 
  5.      
  6.   ) 

在這種情況下,步驟1的非受控value變?yōu)榱?2,步驟3的受控value還是1,所以最終會(huì)用1再更新下DOM的value。

總結(jié)
可以看到,要實(shí)現(xiàn)一個(gè)完備的前端框架,是有非常多細(xì)節(jié)的。

為了實(shí)現(xiàn)受控組件,就得脫離整體更新流程,單獨(dú)實(shí)現(xiàn)一套流程。


當(dāng)前題目:React源碼中如何實(shí)現(xiàn)受控組件
URL分享:http://m.5511xx.com/article/dhjjhge.html