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

React如何原生實(shí)現(xiàn)防抖?

開(kāi)發(fā) 前端
ouseTransition是一個(gè)新增的原生Hook,用于「以較低優(yōu)先級(jí)執(zhí)行一些更新」。在我們的Demo中有ctn與num兩個(gè)狀態(tài),其中ctn與輸入框的內(nèi)容受控。

大家好,我卡頌。

作為前端,想必你對(duì)防抖(debounce)、節(jié)流(throttle)這兩個(gè)概念不陌生。

在React18中,基于新的并發(fā)特性,React原生實(shí)現(xiàn)了防抖的功能。

今天我們來(lái)聊聊這是如何實(shí)現(xiàn)的。

useTransition Dem

ouseTransition是一個(gè)新增的原生Hook,用于「以較低優(yōu)先級(jí)執(zhí)行一些更新」。

在我們的Demo中有ctn與num兩個(gè)狀態(tài),其中ctn與輸入框的內(nèi)容受控。

當(dāng)觸發(fā)輸入框onChange事件時(shí),會(huì)同時(shí)觸發(fā)ctn與num狀態(tài)變化。其中「觸發(fā)num狀態(tài)變化的方法」(即updateNum)被包裹在startTransition中:

function App() {
const [ctn, updateCtn] = useState('');
const [num, updateNum] = useState(0);
const [isPending, startTransition] = useTransition();
return (
<div >
<input value={ctn} onChange={({target: {value}}) => {
updateCtn(value);
startTransition(() => updateNum(num + 1))
}}/>
<BusyChild num={num}/>
</div>
);
}

num會(huì)作為props傳遞給BusyChild組件。在BusyChild中通過(guò)while循環(huán)人為增加組件render所消耗的時(shí)間:

const BusyChild = React.memo(({num}: {num: number}) => {
const cur = performance.now();
// 增加render的耗時(shí)
while (performance.now() - cur < 300) {}
return <div>{num}</div>;
})

所以,在輸入框輸入內(nèi)容時(shí)能明顯感到卡頓。

在線示例地址[1]。

按理說(shuō),onChange中會(huì)同時(shí)觸發(fā)ctn與num的狀態(tài)變化,他們?cè)谝晥D中的顯示應(yīng)該是同步的。

然而實(shí)際上,輸入框連續(xù)輸入一段文字(即ctn的狀態(tài)變化連續(xù)展示在視圖中)后,num才會(huì)變化一次。

如下圖,初始時(shí)輸入框沒(méi)有內(nèi)容,num為0:

輸入框輸入很長(zhǎng)一段文字后,num才變?yōu)?:

這種效果就像:被startTransition包裹的更新都有「防抖」的效果一樣。

這是如何實(shí)現(xiàn)的呢?

什么是lane

在React18中有一套「更新優(yōu)先級(jí)機(jī)制」,不同地方觸發(fā)的更新?lián)碛胁煌瑑?yōu)先級(jí)。優(yōu)先級(jí)的定義依據(jù)是符合用戶感知的,比如:

  • 用戶不希望輸入框輸入文字會(huì)有卡頓,所以onChange事件中觸發(fā)的更新是同步優(yōu)先級(jí)(最高優(yōu))。
  • 用戶可以接受請(qǐng)求發(fā)出到返回之間有等待時(shí)間,所以u(píng)seEffect中觸發(fā)的更新是默認(rèn)優(yōu)先級(jí)。

那么優(yōu)先級(jí)怎么表示呢?用一個(gè)31位的二進(jìn)制,被稱為lane。

比如「同步優(yōu)先級(jí)」和「默認(rèn)優(yōu)先級(jí)」定義如下:

const SyncLane =    0b0000000000000000000000000000001;
const DefaultLane = 0b0000000000000000000000000010000;

數(shù)值越小優(yōu)先級(jí)越大,即SyncLane < DefaultLane。

那么React每次更新是不是選擇一個(gè)優(yōu)先級(jí),然后執(zhí)行所有組件中「這個(gè)優(yōu)先級(jí)對(duì)應(yīng)的更新」呢?

不是。如果每次更新只能選擇一個(gè)優(yōu)先級(jí),那靈活性就太差了。

所以實(shí)際情況是:每次更新,React會(huì)選擇一到多個(gè)lane組成一個(gè)批次,然后執(zhí)行所有組件中「包含在這個(gè)批次中的lane對(duì)應(yīng)的更新」

這種組成批次的lane被稱為lanes。

比如,如下代碼將SyncLane與DefaultLane合成lanes:

// 用“按位或”操作合并lane
const lanes = SyncLane | DefaultLane;

entangle機(jī)制

可以看到,lane機(jī)制本質(zhì)上就是各種位運(yùn)算,可以設(shè)計(jì)的很靈活。

在此基礎(chǔ)上,有一套被稱為entangle(糾纏)的機(jī)制。

entangle指一種lane之間的關(guān)系,如果laneA與laneB糾纏,那么某次更新React選擇了laneA,則必須帶上laneB。

也就是說(shuō)laneA與laneB糾纏在一塊,同生共死了。

除此之外,如果laneA與laneC糾纏,此時(shí)laneC與laneB糾纏,那么laneA也會(huì)與laneB糾纏。

那么entangle機(jī)制與useTransition有什么關(guān)系呢?

被startTransition包裹的回調(diào)中觸發(fā)的更新,優(yōu)先級(jí)為TransitionLanes中的一個(gè)。

TransitionLanes中包括16個(gè)lane,分別是TransitionLane1到TransitionLane16:

而transition相關(guān)lane會(huì)發(fā)生糾纏。

在我們的Demo中,每次onChange執(zhí)行,都會(huì)創(chuàng)建兩個(gè)更新:

onChange={({target: {value}}) => {
updateCtn(value);
startTransition(() => updateNum(num + 1))
}

其中:

  • updateCtn(value)由于在onChange中觸發(fā),優(yōu)先級(jí)為SyncLane。
  • updateNum(num + 1)由于在startTransition中觸發(fā),優(yōu)先級(jí)為TransitionLanes中的某一個(gè)。

當(dāng)在輸入框中反復(fù)輸入文字時(shí),以上過(guò)程會(huì)反復(fù)執(zhí)行,區(qū)別是:

  • SyncLane由于是最高優(yōu)先級(jí),會(huì)被執(zhí)行,所以我們會(huì)看到輸入框中內(nèi)容變化。
  • TransitionLanes相關(guān)lane優(yōu)先級(jí)比SyncLane低,暫時(shí)不會(huì)執(zhí)行,同時(shí)他們會(huì)產(chǎn)生糾纏。

為了防止某次更新由于優(yōu)先級(jí)過(guò)低,一直無(wú)法執(zhí)行,React有個(gè)「過(guò)期機(jī)制」:每個(gè)更新都有個(gè)過(guò)期時(shí)間,如果在過(guò)期時(shí)間內(nèi)都沒(méi)有執(zhí)行,那么他就會(huì)過(guò)期。

過(guò)期后的更新會(huì)同步執(zhí)行(也就是說(shuō)他的優(yōu)先級(jí)變得和SyncLane一樣)。

在我們的例子中,startTransition(() => updateNum(num + 1))會(huì)產(chǎn)生很多糾纏在一塊的TransitionLanes相關(guān)lane。

過(guò)了一段時(shí)間,其中某個(gè)lane過(guò)期了,于是他優(yōu)先級(jí)提高到和SyncLane一樣,立刻執(zhí)行。

又由于這個(gè)lane與其他TransitionLanes相關(guān)lane糾纏在一起,所以他們會(huì)被一起執(zhí)行。

這就表現(xiàn)為:在輸入框一直輸入內(nèi)容,但是num在視圖中顯示的數(shù)字過(guò)了會(huì)兒才變化。

總結(jié)

今天我們聊了useTransition內(nèi)部的一些實(shí)現(xiàn),涉及到:

  • lane模型。
  • entangle機(jī)制。
  • 更新過(guò)期機(jī)制。

最有意思的是,由于不同電腦性能不同,瀏覽器幀率會(huì)變動(dòng),所以在不同電腦中React會(huì)動(dòng)態(tài)調(diào)節(jié)防抖的效果。

這就相當(dāng)于不需要你手動(dòng)設(shè)置debounce的時(shí)間參數(shù),React會(huì)根據(jù)電腦性能動(dòng)態(tài)調(diào)整。

參考資料

[1]在線示例地址:

??https://codesandbox.io/s/immutable-glade-u0m6vv?file=/src/App.js。??

責(zé)任編輯:姜華 來(lái)源: 魔術(shù)師卡頌
相關(guān)推薦

2024-05-28 09:26:46

2023-12-18 07:37:17

JavaScript防抖節(jié)流

2024-06-14 09:30:58

2024-03-08 08:26:20

防抖節(jié)流delay?

2021-08-03 06:57:36

Js事件節(jié)流

2022-04-14 08:00:00

Cypress測(cè)試開(kāi)發(fā)

2024-08-29 15:26:21

2023-12-21 08:51:37

防抖節(jié)流Vue.js

2024-09-13 10:21:50

2010-09-27 13:16:42

2023-08-29 08:28:43

React并發(fā)更新

2021-12-09 10:57:19

防抖函數(shù) Debounce

2024-10-12 09:33:24

消息隊(duì)列多線程并行編程

2020-10-21 08:38:47

React源碼

2022-08-21 09:41:42

ReactVue3前端

2022-02-22 08:29:59

Vue前端防抖

2016-11-23 16:48:20

react-nativandroidjavascript

2021-09-28 05:51:25

PostTaskReact瀏覽器

2011-03-07 10:26:04

FileZilla

2019-10-08 11:10:18

React自動(dòng)保存前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 手机av在线 | 国产精品91网站 | 久久国产婷婷国产香蕉 | 欧美精品久久 | 久久精品国产免费高清 | a国产一区二区免费入口 | 日韩二三区 | 欧洲一级毛片 | 成人精品免费视频 | 91久久久久久久久久久久久 | 国产片网站 | 日韩第一夜 | 一区二区三区欧美在线观看 | 中文字幕在线精品 | 亚洲成av人片在线观看 | 日韩中文字幕第一页 | 中文字幕一区二区三区在线观看 | 91亚洲精品国偷拍自产在线观看 | 午夜久久久 | 久久中文字幕视频 | 亚洲欧美综合精品久久成人 | 亚洲欧洲一区 | 欧美黄色片 | 黄色网址在线免费观看 | 性色av香蕉一区二区 | 精品国产一区二区三区免费 | 天堂av中文在线 | 日韩亚洲视频 | 久久99精品久久久久子伦 | 亚洲精品国产区 | 91极品视频 | 国产精品欧美一区二区三区不卡 | 奇米视频777| 伊人在线| 亚洲 欧美 综合 | 国产午夜精品久久久久 | 91精品国产一区二区三区蜜臀 | 亚洲一区在线播放 | 瑟瑟视频在线看 | 欧美成人精品激情在线观看 | 狠狠骚 |