精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Ahooks 的 UseClickAway 在 React 17 中不工作了,該怎么辦?

開發(fā) 前端
經(jīng)常用到的組件掛載以及卸載的 useMount、useUnmount,還有支持自動(dòng)請(qǐng)求、手動(dòng)請(qǐng)求、防抖等各種功能請(qǐng)求 useRequest,以及可以將狀態(tài)同步存取到 localStorage 的 useLocalStorageState。

最近公司的前端項(xiàng)目從 React 16 升級(jí)到了 React 17,導(dǎo)致 ahooks 的 useClickAway 不能按預(yù)期工作。

下面西瓜哥我就來說說到底發(fā)生了什么事。

ahooks 中的 useClickAway

ahooks 是阿里巴巴維護(hù)的第三方 React Hook 庫,里面封裝了很多好用的 hook。

比如經(jīng)常用到的組件掛載以及卸載的 useMount、useUnmount,還有支持自動(dòng)請(qǐng)求、手動(dòng)請(qǐng)求、防抖等各種功能請(qǐng)求 useRequest,以及可以將狀態(tài)同步存取到 localStorage 的 useLocalStorageState。

當(dāng)你想要寫一個(gè)與業(yè)務(wù)無關(guān)的第三方 ahooks,你可以去 ahooks 里面找找,大概率能夠找到,是比較優(yōu)秀的 hook 庫。

其中,useClickAway 的作用是 監(jiān)聽目標(biāo)元素外的點(diǎn)擊事件。

useClickAway 接受的第一個(gè)參數(shù)是一個(gè)事件回調(diào)函數(shù)。

第二個(gè)參數(shù)是被排除的目標(biāo)元素,可以是 ref 或 DOM 元素,或者是它們組成的數(shù)組,

第三個(gè)是需要監(jiān)聽的事件類型字符串或事件字符串?dāng)?shù)組。第三個(gè)參數(shù)是可選的,不使用的話默認(rèn)用點(diǎn)擊事件 'click'

下面是一個(gè)常用的寫法:

useClickAway(() => {
console.log('點(diǎn)擊到元素外的地方');
}, ref);

useClickAway 的核心底層原理

核心底層原理是,是在 document 上綁定了一個(gè)冒泡事件。當(dāng)事件冒泡到 document 時(shí),會(huì)判斷事件目標(biāo)元素是否為傳入的 ref 下的子元素。

如果是,什么都不做。如果不是,執(zhí)行回調(diào)函數(shù)。

這里給出 useClickAway 的源碼地址,感興趣的話可以研究一下:

https://github.com/alibaba/hooks/blob/v3.5.0/packages/hooks/src/useClickAway/index.ts。

useClickAway 的問題

如果你在 React 16 中使用 useClickAway,一切都表現(xiàn)良好。

但如果是 React 17 及以上版本使用,在一些情況下會(huì)有問題。

我們有這么一個(gè)場景。

點(diǎn)擊一個(gè)搜索按鈕,會(huì)出現(xiàn)一個(gè)輸入框,此時(shí)用戶需要在這個(gè)輸入框內(nèi)輸入文字來搜索。如果點(diǎn)擊到搜索按鈕外的地方,輸入框會(huì)消失。

ahooks 的 useClickAway 在 React 17 中不工作了

核心實(shí)現(xiàn)如下:

function App() {
const [visible, setVisible] = useState(false);
const inputRef = useRef();
useClickAway(() => {
setVisible(false);
}, inputRef);
return (
<div>
<button onClick={() => setVisible(true)}>搜索</button>
{visible && <input ref={inputRef} autoFocus />}
</div>
);
}

這里提供一個(gè)線上 demo(用的是 React 17 版本):

https://codesandbox.io/s/f54siy。

在 React 16 的時(shí)候,上面的寫法是正常的。但升級(jí)到 17 后,你會(huì)發(fā)現(xiàn)點(diǎn)擊 button 后什么事情都沒有發(fā)生。

React 17 的事件系統(tǒng)改造

?原因在于 React 17 對(duì)事件系統(tǒng)進(jìn)行了改造。

16 升級(jí)到 17 后,React 將事件委托到 ReactDOM 掛載的根節(jié)點(diǎn)上,比如 div#app,而不再是原來 document。

ahooks 的 useClickAway 在 React 17 中不工作了

?首先,我們要知道的是,當(dāng)調(diào)用 setVisible(true) 改變組件狀態(tài)時(shí),組件就立即被重新渲染了,然后調(diào)用了 useClickAway。狀態(tài)更新后的組件重渲染是同步的,此時(shí)我們的事件流其實(shí)還沒有結(jié)束。

需要注意的是,更新狀態(tài)后的組件重新渲染,可能是同步,也可能是異步的。?

在 React 16 中,事件都委托到了 document 上。

我們點(diǎn)擊 button 元素,產(chǎn)生了一個(gè)事件流,當(dāng)點(diǎn)擊事件流動(dòng)到 document 時(shí),我們將 visible 設(shè)置為 true,組件進(jìn)行了一次同步的重新渲染,并調(diào)用 useClickAway,做了個(gè) document 上的冒泡事件綁定。

就像下面這樣:

document.addEventListener('click', () => {
console.log('顯示輸入框')
// React 16 中 useClickAway 綁定事件的時(shí)機(jī)
document.addEventListener('click', () => {
console.log('隱藏輸入框');
});
});
// 點(diǎn)擊后的輸出內(nèi)容為:
// 顯示輸入框

在一個(gè)元素的事件觸發(fā)過程中,往這個(gè)元素上注冊(cè)新的相同類型的事件響應(yīng)函數(shù),這個(gè)新的響應(yīng)函數(shù)不會(huì)在此次事件流上立即觸發(fā)。

所以,前面的 useClickAway 寫法在 React 16 是正常的。

但是,在 React 17 中就不同了,事件委托下放到了 div#app 中。

ahooks 的 useClickAway 在 React 17 中不工作了

點(diǎn)擊按鈕,事件流冒泡到 div#app 元素,執(zhí)行事件回調(diào)函數(shù)將 visible 設(shè)置為了 true,并重新渲染組件,執(zhí)行 useClickAway 再給 document 綁定了新的事件響應(yīng)函數(shù)。

此時(shí)事件流沒有結(jié)束,繼續(xù)冒泡到 document,將 visible 又設(shè)置回了 false。

所以,visible 在短暫地變成 true 后,又變回了 false,無事發(fā)生。

document.querySelector('#app').addEventListener('click', () => {
console.log('顯示輸入框')
// React 17 中 useClickAway 綁定事件的時(shí)機(jī)
document.addEventListener('click', () => {
console.log('隱藏輸入框');
});
});
// 點(diǎn)擊后的輸出內(nèi)容為:
// 顯示輸入框
// 隱藏輸入框

解決方案

方案 1:阻止冒泡

<button
onClick={(e) => {
e.stopPropagation();
setVisible(true);
}}
>

我們給按鈕加上阻止事件冒泡,提前結(jié)束事件流,使其不流到 document 上,就不會(huì)觸發(fā) document 的點(diǎn)擊事件。

但這樣也是有隱患的,e.stopPropagation 是破壞性的。

如果我們?cè)谄渌牡胤揭獙懸恍┨厥獾呐袛嗍Ы惯壿嫞惨玫筋愃?useClickAway 的做法,我們點(diǎn)到這個(gè) button 上就會(huì)讓其他地方的邏輯走不通。

CSS 中的 overflow: hidden; 也具有破壞性,如果設(shè)置了該屬性的容器內(nèi)部的元素超出了容器范圍,會(huì)被截?cái)唷?/span>

方案 2:修改綁定事件類型為 mousedown / touchstart

useClickAway(
() => setVisible(false),
inputRef,
['mousedown', 'touchstart']
);

mousedown 在 click 事件之前就結(jié)束了,所以在 click 事件流過程中不會(huì)觸發(fā)它。

touchstart 是為了兼容移動(dòng)設(shè)備的情況。因?yàn)橛|屏?xí)r,touchstart 一定會(huì)觸發(fā),mousedown 不一定,順帶一提,click 也不一定。

其他的比較優(yōu)秀的第三方 React Hooks 庫,比如 react-use 的 useClickAway,其實(shí)就是用 mousedown 和 touchstart 作為默認(rèn)事件類型。

還有百度的 react-hooks 庫,其下的 useClickOutside 不支持自定義事件類型,但也是用的 mousedown 和 touchstart。

方案 3:將 button 元素也傳給 useClickAway

useClickAway(
() => setVisible(false),
[inputRef, buttonRef]
);

這樣就可以把 button 也排除在觸發(fā)條件外。

但這樣寫很繁瑣。如果輸入框要封裝成一個(gè)組件,你還得把 buttonRef 傳入到這個(gè)組件中。

方案 4:延遲輸入框出現(xiàn)時(shí)機(jī)

<button
onClick={() => {
setTimeout(() => {
setVisible(true);
});
}}
>

通過 setTimeout 的方式,確保輸入框的出現(xiàn)在同步的事件流之后才出現(xiàn),然后才觸發(fā) useClickAway 綁定邏輯。

結(jié)尾

React 16 升級(jí)為 17 后,React 中混合事件托管綁定到了 React 組件樹掛載的 div#app 上,不再是之前的 document。

這讓默認(rèn)注冊(cè)為 click 事件類型的 useClickAway 在一些場景下,表現(xiàn)上和 React 16 有一些不同。

對(duì)于上面的場景以及解決方案,我認(rèn)為最好的是第二種:給 useClickAway 的事件類型設(shè)置為 mousedown 和 touchstart。這種方法更有普適性。

責(zé)任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2021-06-16 06:14:29

React17Toast組件React bug

2019-06-03 10:53:49

MySQL硬盤數(shù)據(jù)庫

2019-01-04 10:20:48

桌面圖標(biāo) 圖標(biāo)閃爍Windows 10

2022-04-22 10:30:07

框架JavaScript前端

2011-06-30 17:58:30

網(wǎng)站被K

2021-03-17 10:55:14

Redis哈希數(shù)據(jù)庫

2022-06-08 08:01:20

useEffect數(shù)組函數(shù)

2010-11-17 11:06:34

跳槽

2018-08-20 19:39:14

區(qū)塊鏈職業(yè)崗位

2016-11-24 14:44:49

云計(jì)算

2010-05-20 16:08:01

亞馬遜故障

2021-01-26 08:02:04

Redis內(nèi)存數(shù)據(jù)庫

2024-10-17 10:25:34

2015-10-22 09:09:59

BAT投資VC

2017-12-08 11:14:21

2013-10-30 13:19:12

2021-02-23 11:10:33

人工智能機(jī)器人工作

2022-09-08 11:39:35

架構(gòu)

2019-04-15 10:45:37

2012-08-13 10:53:28

IT運(yùn)維
點(diǎn)贊
收藏

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

国产亚洲精品久久| 一区二区三区中文字幕电影| 国产成人精品999| 国产精品综合激情| 影音先锋欧美激情| 精品久久久免费| 午夜久久资源| 国产精品探花视频| 亚洲日韩视频| 中文字幕日韩精品在线| 中文在线字幕观看| 日韩精品免费观看视频| 亚洲精品久久7777| 免费h精品视频在线播放| 一级片在线免费观看视频| 亚洲第一黄网| 久热精品视频在线免费观看| 国产精品jizz| 在线日韩成人| 欧美日韩国产综合一区二区三区 | 国产精品久久国产精麻豆99网站 | h狠狠躁死你h高h| 蜜桃久久av| 美女视频黄免费的亚洲男人天堂| 国产精品揄拍100视频| 视频免费一区二区| 欧美亚洲日本国产| 久久久999免费视频| bt在线麻豆视频| 国产亚洲精品中文字幕| 国产精品久久久久久久免费大片 | 久久国产精品99久久久久久丝袜| 一区二区不卡视频在线观看| 久久福利精品| 国内外成人免费激情在线视频网站 | 亚洲欧美综合v| 蜜桃色一区二区三区| 黄色成人在线观看网站| 日韩欧美一区视频| 久激情内射婷内射蜜桃| 手机电影在线观看| 亚洲男人电影天堂| 一本一本久久a久久精品综合妖精| 深夜福利在线观看直播| 成人在线综合网站| 亚洲综合中文字幕在线| 国产精品无码一区二区桃花视频| 久久国产精品99国产| 91国偷自产一区二区三区的观看方式| 九九九久久久久| 久久久久久久久久久久久久| 中日韩午夜理伦电影免费 | 手机看片福利盒子久久| 日韩伦理精品| 精品久久久久久久久久久久久| 国内少妇毛片视频| 国产精品探花在线| 亚洲制服丝袜在线| 日韩国产成人无码av毛片| 久久五月精品中文字幕| 亚洲一区二区3| 男女日批视频在线观看| 免费在线国产视频| 一区二区三区国产豹纹内裤在线| 色乱码一区二区三区熟女| 毛片在线不卡| 亚洲蜜臀av乱码久久精品蜜桃| 懂色av一区二区三区四区五区| 黄色网页在线免费观看| 亚洲免费大片在线观看| 男人添女人下部视频免费| 国产在线xxx| 狠狠躁18三区二区一区| 亚洲成熟丰满熟妇高潮xxxxx| 欧美专区福利免费| 欧美日韩三级视频| www.国产福利| 成人高潮视频| 亚洲精品视频在线播放| 亚洲色图第四色| 久久久久久久久久久9不雅视频| 久热精品视频在线观看一区| 五月天婷婷丁香| 麻豆成人在线| 国产在线高清精品| 好吊色一区二区| 久久久久国产免费免费| 一本久道久久综合| 成人影音在线| 在线精品亚洲一区二区不卡| 人人爽人人爽av| 理论片一区二区在线| 在线观看视频99| 青青草手机在线观看| 老司机一区二区三区| 国产精品亚洲美女av网站| 午夜精品久久久久久久99| 91亚洲精品乱码久久久久久蜜桃| 亚洲国产精品久久久久久女王| 成人在线观看免费网站| 五月天一区二区三区| 日韩一级免费片| 风间由美中文字幕在线看视频国产欧美| 精品视频在线播放免| 欧美a级片免费看| 99精品国产一区二区青青牛奶| 国产精品mp4| 精品国产亚洲AV| 国产亚洲欧美色| www.av蜜桃| 国外成人福利视频| 亚洲成人av中文字幕| 夜夜春很很躁夜夜躁| 国产精品久久| 国产日韩欧美另类| 午夜福利视频一区二区| 亚洲精品国产精品乱码不99| 免费日韩视频在线观看| 91麻豆精品国产91久久久久推荐资源| 国产亚洲视频在线| 国产精品99精品无码视| 久久精品国产精品青草| 欧美13一14另类| 日韩电影免费观看| 欧美探花视频资源| 小毛片在线观看| 欧美精品福利| 91精品在线影院| 98在线视频| 在线视频一区二区三| 亚洲综合自拍网| 国内精品福利| 5566av亚洲| www视频在线看| 欧美日韩免费在线视频| 一区二区三区免费在线观看视频 | 国产在线精品91| 日韩一区网站| 欧美xxxx做受欧美.88| 一级久久久久久久| 国产精品免费av| 青青草av网站| 精品国产乱码久久久久久1区2匹| 78m国产成人精品视频| 日本黄色免费视频| 亚洲成年人影院| 稀缺小u女呦精品呦| 在线成人直播| 亚洲a级在线观看| 国产精品剧情一区二区在线观看| 欧美欧美欧美欧美| 中文乱码字幕高清一区二区| 麻豆视频一区二区| 亚洲欧美日本国产有色 | 极品尤物久久久av免费看| 91青青草免费观看| 手机在线免费看av| 精品欧美久久久| 国产精品1000| 99国产欧美另类久久久精品 | 蜜臀久久99精品久久久久宅男| 日本一区高清不卡| 成人免费一区| 按摩亚洲人久久| 国产又粗又猛又爽| 一区二区免费在线| 蜜臀av粉嫩av懂色av| 国产欧美高清| 麻豆亚洲一区| 成人在线免费| 欧美成人sm免费视频| www久久久com| 精品久久久久久久久久国产| 亚欧洲乱码视频| 久久爱www久久做| 久久久久久久久网| 国产精品45p| 日本亚洲精品在线观看| 午夜在线播放| 日韩美女一区二区三区四区| 精品国产乱码一区二区| 日本一区二区成人在线| 绯色av蜜臀vs少妇| 欧美亚洲视频| 亚洲欧美国产不卡| heyzo欧美激情| 国产福利成人在线| a毛片在线看免费观看| 亚洲黄色av女优在线观看 | 免费不卡av| 日韩成人在线电影网| 最新黄色网址在线观看| 亚洲精品久久久久久国产精华液| 欧美一区二区免费在线观看| 爽好久久久欧美精品| 在线观看免费黄色片| 丁香5月婷婷久久| 国产精品久久久久久超碰| 天堂av在线电影| 亚洲人成电影网站| www.99视频| 在线视频你懂得一区| 欧美做爰爽爽爽爽爽爽| 久久亚洲一区二区三区四区| 91亚洲精品久久久蜜桃借种| 亚洲久久一区| 艳母动漫在线免费观看| 在线日韩一区| 国产91亚洲精品一区二区三区| 123成人网| 亚州精品天堂中文字幕| 黄色网址视频在线观看| 亚洲人精品午夜在线观看| 好吊色一区二区三区| 欧美巨大另类极品videosbest | 四虎永久免费影院| 国产精品中文字幕日韩精品| www.欧美日本| 在线亚洲自拍| 91视频 - 88av| 成人在线免费视频观看| 蜜桃视频在线观看成人| 精品国内亚洲2022精品成人| 91在线国产电影| 日韩毛片免费看| 国产经典一区二区| 中文在线免费视频| 性欧美长视频免费观看不卡| 尤物视频在线看| 久久精品91久久香蕉加勒比| 免费a级毛片在线观看| 亚洲国产精品字幕| www五月婷婷| 日韩精品一区二区三区中文精品| 一级黄色大片免费| 在线观看av不卡| 国产性生活视频| 色婷婷精品大在线视频 | 在线亚洲国产精品网站| av网站大全免费| 欧美日韩四区| 嫩草影院中文字幕| 欧美人成在线| 国产爆乳无码一区二区麻豆| 亚洲乱码免费伦视频| 国产成人精品免费看在线播放| 日韩一区欧美| 亚洲蜜桃av| 久久久久av| 欧美一级爱爱视频| 狠狠色狠狠色综合日日tαg| 日韩成人三级视频| 影音先锋日韩资源| 很污的网站在线观看| 日韩网站在线| 国产精品免费成人| 蜜桃传媒麻豆第一区在线观看| 国产三级三级三级看三级| 看片网站欧美日韩| 国产一区二区在线观看免费视频| 国内精品免费**视频| 日本一本在线视频| 成人精品电影在线观看| 国产成人无码一区二区在线观看| 久久只精品国产| 永久免费毛片在线观看| 中文字幕av在线一区二区三区| 战狼4完整免费观看在线播放版| 亚洲欧美国产77777| 精品在线视频观看| 狠狠色狠狠色综合日日小说| 久久影视中文字幕| 欧美美女网站色| 亚洲精品国产一区二| 亚洲精品久久久久| yourporn在线观看视频| 久久中文久久字幕| 精品捆绑调教一区二区三区| 日韩免费中文字幕| av日韩一区| 国产一区自拍视频| 青青草国产成人a∨下载安卓| 无码人妻aⅴ一区二区三区日本| 亚洲黄色影片| 丰满少妇在线观看| 国产福利一区二区三区视频在线 | av男人天堂网| 亚洲国产欧美久久| 9191在线观看| 午夜精品美女自拍福到在线| 亚洲电影有码| 99久久久精品免费观看国产| 久久超碰99| 一级性生活视频| 久久综合激情| 任你躁av一区二区三区| 国产欧美一区二区精品仙草咪| 性欧美videos| 日本电影亚洲天堂一区| 国产情侣在线播放| 亚洲欧美中文字幕| 婷婷av在线| 国产女人18毛片水18精品| 波多野结衣在线一区二区| 色狠狠久久av五月综合| 在线观看日韩av电影| 国产精品自拍视频在线| 91在线视频播放地址| 全网免费在线播放视频入口| 在线视频你懂得一区二区三区| 欧美特级特黄aaaaaa在线看| 最近中文字幕日韩精品 | 欧美h版在线| 各处沟厕大尺度偷拍女厕嘘嘘| 狠狠色丁香九九婷婷综合五月| 久久精品女同亚洲女同13| 日韩美女视频19| 无码人妻一区二区三区免费| 欧美精品一区二| 很黄的网站在线观看| 日韩美女福利视频| 琪琪久久久久日韩精品| 永久免费网站视频在线观看| 蜜臀精品一区二区三区在线观看| a天堂视频在线观看| 一区二区在线观看免费| 国产精品久久久久毛片| 中文国产成人精品| 澳门av一区二区三区| 裸体丰满少妇做受久久99精品| 精品福利av| 亚洲制服在线观看| 日韩理论片中文av| 一区二区精品视频在线观看| 国产一区二区三区高清在线观看| 中文字幕乱码中文乱码51精品| 国内外成人免费视频| 黄色另类av| 国产精品一区二区无码对白| 一区二区三区av电影 | 亚洲九九九在线观看| 182在线视频观看| 国产伦精品一区二区三区免费视频 | 亚洲精品久久久久久下一站 | 人成在线免费视频| 97色在线观看| 欧美亚洲色图校园春色| 怡红院av亚洲一区二区三区h| 99热这里都是精品| av大片在线免费观看| 日韩精品丝袜在线| 欧美大电影免费观看| 欧美一进一出视频| 久久久精品网| 久久午夜福利电影| 在线一区二区三区做爰视频网站| 九九在线视频| 国产精品免费福利| 午夜影院欧美| 亚洲av无一区二区三区久久| 一区二区三区中文字幕电影 | 国产免费av国片精品草莓男男 | 国产日韩亚洲| 一级特黄曰皮片视频| 欧美日韩高清一区二区不卡 | 国内黄色精品| 宅男噜噜噜66国产免费观看| 综合精品久久久| 亚洲第一大网站| 97成人超碰免| 成人短片线上看| 亚洲成人手机在线观看| 亚洲国产欧美另类丝袜| 免费福利在线观看| 91日韩在线视频| 亚洲日韩成人| 男女男精品视频网站| 精品黑人一区二区三区久久| 中文字幕高清在线播放| 中文字幕久久综合| 成人小视频在线| 欧美超碰在线观看| 久久综合网hezyo| 精品福利一区| 999在线观看| 激情成人在线视频| jizz视频在线观看| 国产精品一区二区三区在线观| 久久精品综合| 99热精品免费| 亚洲日本中文字幕| 日韩精品一级| 欧美先锋影音| 国模精品一区二区三区| 久久久精品网| 日韩一区二区三区四区在线| 日韩电视剧在线观看免费网站| 国产精品99| 久草热视频在线观看| 国产精品久久久久久久久免费相片 |