精品欧美一区二区三区在线观看 _久久久久国色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)

国产欧美激情视频| 国产精品污www一区二区三区| 亚洲天堂网一区二区| 日本电影欧美片| 中文字幕一区av| 国产精品永久入口久久久| 日本特级黄色片| 97精品视频在线看| 亚洲大胆人体av| 午夜欧美福利视频| 波多一区二区| 中文字幕二三区不卡| 不卡视频一区二区三区| 国产一级做a爱片久久毛片a| 国产韩国精品一区二区三区| 亚洲国产精品va| 亚洲黄色av片| www.com.cn成人| 亚洲一区二区在线免费看| 日韩欧美三级电影| 国产18精品乱码免费看| 久久成人免费电影| 456亚洲影院| 青娱乐国产在线视频| 精品国产91| 亚洲成人激情图| 天堂在线中文在线| 粉嫩一区二区三区| 亚洲综合无码一区二区| 中文精品一区二区三区| 精品欧美不卡一区二区在线观看 | 午夜精品久久久久久久99老熟妇| 久久激情久久| 97香蕉超级碰碰久久免费软件| 免费精品在线视频| 国产成人短视频在线观看| 亚洲国产精品久久久久| 亚洲国产日韩在线一区| 曰本一区二区| 欧美日韩中文字幕一区| 国产熟人av一二三区| 神马久久午夜| 亚洲va天堂va国产va久| 成人在线免费观看视频网站| 美女国产在线| 综合在线观看色| 五月天色一区| h网站视频在线观看| 国产偷v国产偷v亚洲高清| 农村寡妇一区二区三区| 亚洲av成人无码网天堂| aaa欧美日韩| 国产精品一区二区三区不卡 | 成人黄色在线网站| 亚洲xxx大片| 99久久精品免费看国产交换| 久99久精品视频免费观看| 国产精品欧美一区二区三区奶水| 无码视频一区二区三区| 久久久精品性| 国产精品久久久一区| 日韩乱码一区二区三区| 奇米影视一区二区三区| 国产精品一区久久| 国产精品视频久久久久久| 国产综合久久久久久久久久久久| 91香蕉亚洲精品| 国产成人久久精品77777综合 | 91九色蝌蚪国产| 国产精品毛片久久久久久久av | 西西大胆午夜视频| 日本天堂一区| 亚洲三级黄色在线观看| 日本黄色激情视频| 亚洲女同一区| 久久久在线视频| 久久国产黄色片| 日日夜夜精品视频天天综合网| 国产精品福利网| 国产又大又黄的视频| 国产高清成人在线| 精品一区二区三区免费毛片| 国产网站在线播放| 亚洲男女一区二区三区| 中文字幕无码精品亚洲资源网久久| 成人性生交大片免费看网站| 色婷婷综合久色| 天天色综合社区| 亚洲成人偷拍| 亚洲欧美视频在线| 99自拍视频在线| 国产亚洲永久域名| 国产主播欧美精品| 人妻妺妺窝人体色www聚色窝| 久久久久国产免费免费| 熟女视频一区二区三区| 懂色av一区| 在线视频一区二区免费| 亚洲av毛片在线观看| 亚洲a级精品| 久久手机免费视频| 天天操天天爽天天干| 久久se这里有精品| 九9re精品视频在线观看re6| 永久免费av片在线观看全网站| 亚洲一区二区中文在线| 天天干天天操天天玩| 成人知道污网站| 色系列之999| 日操夜操天天操| 精品中文字幕一区二区小辣椒| 精品国产一二| 成人三级网址| 91久久国产最好的精华液| 不许穿内裤随时挨c调教h苏绵| 精品福利久久久| 91chinesevideo永久地址| 99视频免费看| 日本一区二区视频在线| 青青青免费在线| 成人在线啊v| 一区二区三区日韩在线| 国产精品a成v人在线播放| 久久er精品视频| 欧美亚洲爱爱另类综合| 岛国片av在线| 日韩女优电影在线观看| 国产wwwwxxxx| 免费在线观看视频一区| 麻豆精品传媒视频| 18aaaa精品欧美大片h| 欧美疯狂性受xxxxx喷水图片| 18禁裸乳无遮挡啪啪无码免费| 国产精品二区影院| 99三级在线| 污污影院在线观看| 欧美一区二区三区人| 日本在线观看网址| 日韩综合在线视频| 欧美日韩一区二区三| 国产精品xx| 精品国产凹凸成av人导航| 麻豆changesxxx国产| 黑人巨大精品欧美一区| 亚洲看片网站| 另类一区二区三区| 日韩中文字幕国产| 中文字幕免费高清在线观看| 国产欧美一区二区三区鸳鸯浴 | 粉嫩av一区二区三区粉嫩 | 久久久精品午夜少妇| 欧美极品一区二区| 久久久一本精品| 亚洲日本成人女熟在线观看| 无码人妻丰满熟妇区五十路| 久久久久久久久久美女| 久久久久久香蕉| 国产videos久久| 国产精品激情自拍| 在线a免费看| 欧美疯狂做受xxxx富婆| 欧美成人国产精品高潮| 国产不卡在线播放| 少妇高潮喷水在线观看| 亚洲制服欧美另类| 国产精品wwww| 免费a级毛片在线播放| 欧美一级xxx| 国产精品二区一区二区aⅴ| www亚洲一区| 亚洲成色www.777999| 国产精品成人a在线观看| 成人激情电影一区二区| 色yeye免费人成网站在线观看| 精品欧美乱码久久久久久1区2区| 日本一二三区视频| 久久久av毛片精品| 麻豆三级在线观看| 欧美激情aⅴ一区二区三区| 国产另类自拍| 日韩不卡免费高清视频| 精品国产一区二区三区在线观看 | 国产福利91精品一区| 成人免费在线网| 欧美美女一区| 91手机在线视频| 久久青青视频| 欧美刺激性大交免费视频| 色婷婷av一区二区三区之红樱桃| 欧美日韩一区二区在线| 永久免费看片直接| 99视频精品免费视频| 五月婷婷狠狠操| 欧美日韩亚洲一区| 日本一区高清不卡| 综合欧美亚洲| 51精品国产黑色丝袜高跟鞋 | 国产精品美女久久久久久久久久久 | 欧美18视频| 久久伊人精品| 国产福利视频一区二区| 日本高清在线观看| 国产一区二区三区高清在线观看| 亚洲国产精品久久人人爱潘金莲| 91久久人澡人人添人人爽欧美| 久久久久久久久久久网| 国产精品素人视频| 欲求不满的岳中文字幕| 国产美女在线精品| 午夜久久久精品| 亚洲少妇一区| 女人床在线观看| 日本女优一区| 欧美日产一区二区三区在线观看| 精品国产麻豆| 国产精品男女猛烈高潮激情| 国产黄大片在线观看| 久久6精品影院| 日本在线视频站| 亚洲欧美成人网| 黄色av小说在线观看| 欧美精品 国产精品| 成人av网站在线播放| 天天综合天天综合色| 麻豆疯狂做受xxxx高潮视频| 国产精品精品国产色婷婷| 丝袜美腿中文字幕| 99国产麻豆精品| aaa黄色大片| 国产精品正在播放| 57pao国产成永久免费视频| 日韩av一级片| 日韩中文字幕免费在线| 亚洲综合好骚| www.99热这里只有精品| 亚洲国产一区二区精品专区| 99视频精品全部免费看 | 男女猛烈激情xx00免费视频| 最新国产精品久久久| 艳色歌舞团一区二区三区| 狠狠操综合网| 欧美日韩亚洲综合一区二区三区激情在线| 久久99精品国产自在现线| 国产精品一区视频| 韩国女主播一区二区三区| 国产精品一区二区av| 国产伦精品一区二区三区免费优势| 99在线观看视频网站| 亚洲电影一区| 国产精品永久入口久久久| 极品束缚调教一区二区网站| 久久婷婷人人澡人人喊人人爽| 精品福利一区| 久久久久久久免费| 国产91精品对白在线播放| 茄子视频成人在线观看| 成人免费电影网址| 亚洲一区二三| 亚洲精品成人| 美女黄色免费看| 99成人精品| 日本三区在线观看| 日本成人中文字幕在线视频| 奇米影视四色在线| 国产精品一区三区| 国产草草浮力影院| 久久久综合激的五月天| 手机看片日韩av| 亚洲三级理论片| 国产精品第108页| 91久久精品一区二区三区| 国产精品无码久久av| 日韩精品在线网站| 日韩三级电影网| 在线观看日韩欧美| 51xtv成人影院| 97在线视频免费看| 成人在线视频播放| 91欧美精品午夜性色福利在线| 99热这里只有精品首页| 蜜桃精品久久久久久久免费影院 | av免费看网址| 久久一区视频| 在线免费看v片| 91小视频在线观看| 极品色av影院| 精品成人在线视频| 91午夜交换视频| 日韩av在线电影网| 欧美日韩xx| 91精品国产色综合久久不卡98| 国产毛片精品久久| 国产精品白丝jk白祙| 精品久久中文| 亚洲色欲久久久综合网东京热| 首页国产欧美日韩丝袜| 国产探花一区二区三区| 久久久精品国产99久久精品芒果 | 熟妇高潮精品一区二区三区| 国产精品久久久久久久久果冻传媒| 精品视频在线观看免费| 欧美日韩专区在线| 天天av综合网| 精品视频9999| 丁香婷婷久久| 免费国产一区| 韩日精品视频| 欧美成人福利在线观看| 91原创在线视频| 欧洲猛交xxxx乱大交3| 欧美午夜影院一区| 亚洲 另类 春色 国产| 欧美肥婆姓交大片| 成人免费一区| 六月婷婷久久| 亚洲高清二区| 1314成人网| 国产精品灌醉下药二区| 波多野结衣午夜| 日韩精品在线免费观看视频| av超碰免费在线| 国产拍精品一二三| 国产日韩欧美一区二区三区| 无码中文字幕色专区| 国产成人精品一区二| 在线观看亚洲网站| 欧美三级电影精品| 国产午夜精品一区理论片| 欧美诱惑福利视频| 好吊妞国产欧美日韩免费观看网站| 欧美 国产 精品| 韩国成人精品a∨在线观看| 日本一卡二卡在线播放| 欧美专区在线观看一区| 黄色片视频在线观看| 日产日韩在线亚洲欧美| 天堂成人娱乐在线视频免费播放网站 | 国产精品久久久久久亚洲色 | 亚洲 欧美 日韩 综合| 精品国产凹凸成av人网站| 97在线视频免费观看完整版| av日韩中文字幕| 欧美日韩亚洲一区二区三区在线| 三级网站免费看| 亚洲黄色小视频| 亚洲国产精彩视频| 欧美贵妇videos办公室| 日本精品视频| 99久久久精品视频| 成人永久看片免费视频天堂| 黄页网站免费观看| 亚洲成av人片在线观看香蕉| 成人性生交大片免费看在线播放| 国产精选一区二区| 久久av一区| 国产人妻大战黑人20p| 欧美中文字幕一区| 视频三区在线| 91久久精品一区二区别| 亚洲成人原创| 国产特黄级aaaaa片免| 欧美性色综合网| 黄色一级片在线观看| 亚洲最大福利视频网站| 伊人蜜桃色噜噜激情综合| 最近中文字幕无免费| 在线免费观看日本一区| 天堂аⅴ在线地址8| 91精品国产综合久久久久久丝袜 | 欧美日韩成人在线播放| 国产精品网在线观看| av动漫免费看| 国产精品第一页第二页第三页| 99热精品在线播放| 91黄色8090| 欧美日韩一二| 精品人妻一区二区三| 欧美性猛交xxxx偷拍洗澡| a中文在线播放| 成人午夜电影在线播放| 老司机一区二区三区| 亚洲av无一区二区三区| 欧美mv日韩mv国产| 色婷婷综合久久久中字幕精品久久| 亚洲欧洲精品一区二区三区波多野1战4 | 91九色精品国产一区二区| 国产精九九网站漫画| 岛国av一区二区在线在线观看| av电影在线观看| 成人欧美一区二区三区视频| 视频在线观看国产精品| 91视频综合网| 亚洲欧美中文另类| 日本免费精品| 日本va中文字幕| 一区二区三区四区在线| 国产天堂在线| 国产日韩欧美精品| 精一区二区三区| 日本视频网站在线观看|