摘要:而為對象時,可用選項如下之所以第三個參數(shù)有兩種形態(tài),是在舊版本中只存在一個布爾值,即屬性但隨著時間推移以及發(fā)展的需要,需要支持設(shè)置更多的特性設(shè)置,所以有了選項這個對象傳參,又為了兼容以前的老程序,所以對兩者進(jìn)行了兼容。
起因
最近在看以前的代碼時,發(fā)現(xiàn)年初在熟悉react hooks新特性時寫下了這樣一段代碼:
let i = 0; function Test(props) { const { loading, error, startFetch } = props; useEffect(() => { const $btn = document.querySelector(".btn"); // .info-con 存在于外層的dom中 $btn.addEventListener("click", () => { const action =`action data${i++}`; console.log("resbtn", action); }, false); return $btn.removeEventListener("click", () => {}); }); if (error) { return{error.msg}; } return ({loading &&); }loading
}finished
Saga模擬測試
我用了addEventListener和removeEventListener來嘗試useEffect的掛載和清除功能,細(xì)心的你,發(fā)現(xiàn)這段代碼有幾個錯誤呢?
自我觀察,自認(rèn)為是有如下幾個的:
清除函數(shù)使用方式錯誤,應(yīng)該返回的是一個函數(shù),like:() => { $btn.removeEventListener("click", () => {}); },而我這里是一個語句;
removeEventListener使用語法錯誤;
useEffect未使用第二個參數(shù),導(dǎo)致addEventListener掛載會多次執(zhí)行(可以優(yōu)化)
第1個和第3個錯誤,是可以原諒的,當(dāng)時自己對hooks還不熟悉。但第二個錯誤,是不可原諒的,這是需要檢討的。本文后面不會對useEffect做深入講解,官方文檔已經(jīng)足夠清楚,后面圍繞removeEventListener來剖析。
認(rèn)清removeEventListener第二個錯誤,拆開看,又可分為兩個方面:removeEventListener使用方式多余與語法錯誤。
使用方式多余:雖然$btn添加了click監(jiān)聽事件回調(diào),但由于這個節(jié)點屬于當(dāng)前Test組件,所以組件銷毀時,其相關(guān)節(jié)點的監(jiān)聽事件也會一并銷毀,這個在自己剛接觸前端時就做過這一方面的解析,所以這里的removeEventListener使用是多余的。但如果換成一個組件外的節(jié)點,比如我后面替換的.info-con節(jié)點,這是一直存在于Layout組件中的,使用removeEventListener是必要的。
語法錯誤:指使用removeEventListener,前面兩個參數(shù)是必傳的,事件類型(type:click),事件回調(diào)函數(shù)(listener: callback),由于使用addEventListener是為事件添加的一個隊列(即同一個事件,可添加多個監(jiān)聽回調(diào)),所以事件回調(diào)函數(shù)(listener)是必傳,且其引用與添加的事件監(jiān)聽回調(diào)函數(shù)指向相同。詳細(xì)描述見官方文檔
關(guān)于語法錯誤,官方文檔中有這樣一段描述:
由于我在添加監(jiān)聽時,使用的是箭頭函數(shù),所以刪除時無法找到相同引用的監(jiān)聽事件,所以第一件事就是改變監(jiān)聽函數(shù)的寫法。完善后,寫法是下面這樣的:
let i = 0; function Test(props) { const { loading, error, startFetch } = props; useEffect(() => { const $btn = document.querySelector(".info-con"); const eventAction = () => { const action =`action data${i++}`; console.log("resbtn:", action); }; $btn.addEventListener("click", eventAction); return () => { $btn.removeEventListener("click", eventAction); }; }, []); if (error) { return{error.msg}; } return ({loading &&); }loading
}finished
Saga模擬測試
到此,看似已經(jīng)結(jié)束了。但既然已經(jīng)打開了,就深入的學(xué)習(xí)一下這個api吧,常用的前兩個參數(shù),我們都很熟悉,第三個參數(shù)寫成布爾值也偶爾會有,但是否已足夠了解呢?
第三個參數(shù)addEventListener和removeEventListener傳參是一樣的,第三個可選參數(shù)都是一個對象或者一個布爾值:
target.addEventListener(type, listener[, options]); target.addEventListener(type, listener[, useCapture]); target.removeEventListener(type, listener[, options]); target.removeEventListener(type, listener[, useCapture]);
當(dāng)參數(shù)為布爾值時,意指useCapture,是否在捕獲階段觸發(fā)監(jiān)聽函數(shù)。而為對象時,可用選項如下:
clipboard.png
之所以第三個參數(shù)有兩種形態(tài),是在舊版本中只存在一個布爾值,即useCapture屬性;但隨著時間推移以及發(fā)展的需要,需要支持設(shè)置更多的特性設(shè)置,所以有了options選項這個對象傳參,又為了兼容以前的老程序,所以對兩者進(jìn)行了兼容。once和passive屬性非常有趣,但我還沒想到合適的使用它們的場景。查看官方文檔,發(fā)現(xiàn)里面確實有好多以前沒有關(guān)注到的東西,值得細(xì)細(xì)品味。
其實在js很多api中,我們都只用了一些常用的用法,而忽略了一些存在且也很適用的不常用傳參,比如下面這些:
setTimout(callback, time, ...params): 這個有多有用呢,有一道網(wǎng)紅面試題,關(guān)于閉包的,就可以利用這個參數(shù)來解決,在詳解網(wǎng)紅前端經(jīng)典面試題:setTimeout與循環(huán)閉包提到過
function test(){ for (var i=0; i<5; i ) { setTimeout( function timer() { console.log(new Date(),i); }, 1000); } console.log("end",new Date(),i); }
bind(thisArg, ...params): 為函數(shù)預(yù)先傳參,在react中用的比較多;
replace(reg, str | function): replace第二參數(shù)也可以為一個函數(shù),用于自定義替換
split(reg, length): split其實也是有第二個參數(shù)的,用以指定返回數(shù)組的長度不超過指定大小;
暫時想不起來了...
思考這一次關(guān)于對removeEventListener的使用錯誤,讓我不得不意識到,對于自己下一步技術(shù)提升的著重點還是該多關(guān)注基礎(chǔ),不要學(xué)的太寬泛,而成為泛而不精的人,最后一無是處。最近這一年確實太癡迷(yilai)于框架(React),基礎(chǔ)關(guān)注的太少??蚣芘c基礎(chǔ),框架層出不窮,但基礎(chǔ)只是持續(xù)在演進(jìn)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/106381.html
摘要:我們需要的最好效果肯定是當(dāng)前的全局事件就在當(dāng)前的組件下產(chǎn)生作用,當(dāng)我們切換到其他組件時,事件自動刪除,于是我可能想到的就是利用鉤子函數(shù)去刪除這個全局事件。 最近在自學(xué) Vue 也了解了一些基本用法,也記錄了一些筆記有興趣的朋友可以去查看我的其他文章,技術(shù)這東西真的不能光靠看,看是沒有的,你必須要動手實踐,只有在實戰(zhàn)項目中才能發(fā)現(xiàn)問題,才能發(fā)現(xiàn)我們沒有掌握的知識點,然后發(fā)現(xiàn)問題解決問題,...
摘要:源碼真的這么可怕嗎從以上的事例中可以看出,其實并沒有。對于源碼的恐懼,讓我們漸漸思維固化,自己告訴自己不要去碰源碼,時間長了就遺忘了還有這樣一條路可走。 一個小需求 事情的起因,是昨天有一個新的需求被提出。 需求是要實現(xiàn),讓我們自己定制的彈出層,具備按下 ESC 也能退出的功能。我把任務(wù)交給了同組的小伙伴S去實現(xiàn)。(這個項目用到了vue技術(shù)棧,以及餓了么的UI框架。) 我開完會回來,發(fā)...
摘要:三級事件處理程序級事件定義了兩個方法,分別用于處理指定和刪除事件處理程序的操作和,他們都接收三個參數(shù)要處理的事件名作為事件處理程序的函數(shù)一個布爾值。布爾值如果是表示在捕獲階段調(diào)用事件處理程序,如果是表示在冒泡階段調(diào)用事件處理程序。 前言:擼完CSS-DOM緊接著來擼DOM事件,事件總結(jié)完成后我要開始總結(jié)動畫,然后用純JS實現(xiàn)一個輪播圖,前路漫漫,還有各種框架等著我~~~本篇主要內(nèi)容有:...
摘要:問題初探索刪掉那一點重寫的代碼后,表現(xiàn)符合預(yù)期了。每一次都重新造一個虛擬的,然后監(jiān)聽其自定義事件,并且立即觸發(fā)這個自定義事件。真的不要隨便重寫原生方法。。。于是,我全面總結(jié)一下了中的事件系統(tǒng),也算是對基礎(chǔ)的鞏固。 寫在前面 前段時間,我寫過一篇文章前端開發(fā)中的Error以及異常捕獲。 在文章中,我提到了這個問題: showImg(https://segmentfault.com/img...
摘要:中一個運(yùn)算符優(yōu)先級問題引發(fā)的思考題目假設(shè)已經(jīng)聲明可定義為任何值。分析因為我們忽略了運(yùn)算符的優(yōu)先級。要知道,加號優(yōu)先級高于三目運(yùn)算,低于括號。為值,在里的判斷就是值。 JavaScript中一個運(yùn)算符優(yōu)先級問題引發(fā)的思考 題目 假設(shè) val 已經(jīng)聲明,可定義為任何值。則下面js代碼有可能輸出的結(jié)果為: console.log(Value is + (val != 0) ? define...
閱讀 1374·2023-04-25 19:33
閱讀 1240·2021-10-21 09:39
閱讀 3710·2021-09-09 09:32
閱讀 2714·2019-08-30 10:58
閱讀 1721·2019-08-29 16:17
閱讀 932·2019-08-29 15:29
閱讀 2962·2019-08-26 11:55
閱讀 2725·2019-08-26 10:33