成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

React源碼中如何實現受控組件

開發 前端
今天我們站在框架開發者的角度來聊聊如何實現受控組件。

[[347457]]

今天我們站在框架開發者的角度來聊聊如何實現受控組件。

在React中一個簡單的受控組件如下:

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

在onChange中會更新num,num作為value prop傳遞給<input/>,達到value受控的目的。

如果讓你來設計,你會怎么做?

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

我們知道React內部運行有3個階段:

  • schedule 調度更新階段
  • render 進行diff算法的階段
  • commit 進行DOM操作的階段

假設我們要在onChange中觸發更新改變className,只需要在render階段記錄要改變的className,在commit階段執行對應的addClass DOM操作。

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

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

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

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

想想我們將1234修改為12534。

  1. 1234 --> 12534 

需要先將光標位置移動到2之后,再輸入5。

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

那么React如何解決這個問題呢?

用非受控的形式實現受控組件

你沒有看錯,React用非受控形式實現了受控組件的邏輯。

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

因為一旦更新value,那么光標位置就會丟失。

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

  1. function App() { 
  2.   const num = 1; 
  3.  
  4.   return ( 
  5.     <input value={num}/> 
  6.   ) 

當我們在源碼中打上斷點,輸入2后,實際上會先顯示12,再刪掉2。

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

所以,不同于React其他組件props的更新會經歷schedule - render - commit流程。

對于input、textarea、select,React有一條單獨的更新路徑,這條路徑觸發的更新被稱為discreteUpdate。

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

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

什么情況下這2個value會相同呢?

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

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

什么情況下這2個value會不同呢?

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

  1. function App() { 
  2.   const num = 1; 
  3.  
  4.   return ( 
  5.     <input value={num}/> 
  6.   ) 

在這種情況下,步驟1的非受控value變為了12,步驟3的受控value還是1,所以最終會用1再更新下DOM的value。

總結
可以看到,要實現一個完備的前端框架,是有非常多細節的。

為了實現受控組件,就得脫離整體更新流程,單獨實現一套流程。

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2021-03-18 08:00:55

組件Hooks React

2022-07-06 08:29:12

antdInput 組件

2021-07-09 08:33:35

React組件受控

2021-02-26 15:10:00

前端React組件交互

2021-07-15 07:23:25

React動畫頁面

2023-01-01 23:42:22

React框架暗黑模式

2019-10-08 11:10:18

React自動保存前端

2016-11-25 13:50:15

React組件SFC

2022-05-13 08:48:50

React組件TypeScrip

2022-07-18 09:01:58

React函數組件Hooks

2023-04-06 09:41:00

React 組件重渲染

2021-09-26 18:43:48

表單受控React

2020-12-20 10:02:17

ContextReactrender

2021-12-13 14:37:37

React組件前端

2023-12-21 10:26:30

??Prettier

2019-07-22 10:42:11

React組件前端

2022-05-15 22:08:58

ReactHookdebounce

2023-01-29 08:00:00

Instagram濾鏡圖片編輯

2021-10-11 09:41:20

React位運算技巧前端

2020-05-20 14:25:45

Reactreact.js前端
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: a爱视频 | 亚洲福利一区 | 日韩区| 欧美八区 | 国产福利在线 | 欧美成人精品欧美一级 | 久久久久久久久91 | 日韩精品一区二区三区 | 午夜欧美| 成人激情免费视频 | 日韩欧美在线观看 | 毛片黄| 四虎成人在线播放 | 国产欧美日韩一区 | 国产精品久久久久9999鸭 | 亚洲一区自拍 | 日韩国产在线观看 | 久久久亚洲成人 | 蜜桃av一区二区三区 | 自拍偷拍在线视频 | 一区二区三区在线播放 | 日韩美女在线看免费观看 | 国产亚洲第一页 | 99精品欧美一区二区蜜桃免费 | 天天干精品 | 精品成人在线 | 一二三在线视频 | 中文字幕av网站 | 一级毛片在线播放 | 欧美综合一区二区 | 精品中文字幕在线 | 色视频网站 | 国产精品视频专区 | 日韩欧美1区2区 | 成人av播放 | av大片 | 成人超碰在线 | 免费观看毛片 | 国产成人jvid在线播放 | 国产精品毛片久久久久久 | 成人精品国产一区二区4080 |