您好,登錄后才能下訂單哦!
最近在自學(xué) Vue 也了解了一些基本用法,也記錄了一些筆記有興趣的朋友可以去查看我的其他文章,技術(shù)這東西真的不能光靠看,看是沒有的,你必須要動手實踐,只有在實戰(zhàn)項目中才能發(fā)現(xiàn)問題,才能發(fā)現(xiàn)我們沒有掌握的知識點,然后發(fā)現(xiàn)問題解決問題,我們的能力才能得以提升,要不然就有點眼高手低了。
基于這個想法于是就開始自己去擼了一個旅游網(wǎng)站,旅游網(wǎng)站嘛避免不了城市的選擇,所以在實現(xiàn)城市選擇列表的時候碰到的一些問題,以及解決辦法今天就記錄下來做一個總結(jié)。
城市列表選擇組件
首先說說我們要實現(xiàn)一個什么樣的城市選擇組件:
下面我們就一步一步的來拆解
第一步
輸入框獲取焦點后顯示組件很簡單,我們給輸入框綁定焦點事件然后給組件傳入一個顯示的狀態(tài)即可,我們把 isShowCityList 傳遞給城市選擇組件控制行為。
<el-input @focus="isShowCityList=true" placeholder="請輸入目的地"> </el-input>
第二步
我們也不做過多的表述本文想更多的是介紹動態(tài)組件與全局事件的綁定,利用的是子組件給父組件利用自定義事件 $emit 傳給父組件。
第三步
需要我們?nèi)c擊其他地方城市組件被隱藏,有些同學(xué)的第一印象可能是利用 input 的 blur 事件(就是失去焦點事件),只要我們的 input 失去焦點時,我們就隱藏。
其實我的第一印象也是如此,但是我們綁定的是 input 的失去焦點事件以后,當(dāng)我們選擇城市列表的時候也是 input 失去焦點的時候,所以我們就無法選取城市。顯然這種思路是不行的。
所以這里我們只能去用到 Vue 的全局事件的綁定,然后去進(jìn)行一個判斷我們點擊的節(jié)點是哪里,如果是城市組件以外我們就進(jìn)行隱藏操作。
我們在 mounted 鉤子函數(shù)中,進(jìn)行如下操作。
mounted() { document.addEventListener("click", e => { console.log('全局事件被觸發(fā)'); if (!this.$refs.searchCity.contains(e.target)) { this.isLoadCityList = false; } }); }
OK,進(jìn)行這一步之后,我們的問題得到了解決,只要我們點擊這個容器以外的地方就會隱藏城市列表組件,我以為算是結(jié)束了,不過那是不可能的,還是我太年輕了,這樣做的后果就是不管我們點擊任何一個地方它都會觸發(fā)這個事件,即使是我們切換到其他組件時,事件照樣會被觸發(fā),顯然這個不是我們想要的,因為當(dāng)前事件會被無限觸發(fā),無疑會給我們帶來不可預(yù)見的問題。
我們需要的最好效果肯定是當(dāng)前的全局事件就在當(dāng)前的組件下產(chǎn)生作用,當(dāng)我們切換到其他組件時,事件自動刪除,于是我可能想到的就是利用 beforeDestroy 鉤子函數(shù)去刪除這個全局事件。也就是當(dāng)我們切換到其他組件時,去刪除這個全局事件。
beforeDestroy() { document.removeEventListener("click", () => { //... }); }
你以為這樣我還就能解決問題了嗎?顯然還是不能,還是太年輕,只是這樣我們是解除不了綁定的事件,那我們該怎么辦呢?其實這里面有一個坑,大坑,因為這個大坑自己不知道,差了許多資料也沒查出來,因為差的思路錯了,最后在一個群里問了一個大佬,才得出答案,不得不說與前輩交流很重要啊,能幫你少踩很多坑。
這里如果想要解除綁定,解除和綁定的兩個回調(diào)函數(shù)必須一致,什么意思呢?看代碼你就明白。如果不這么操作,你是解除不掉事件的,至于更深的原因我也不怎么明白了,以后再去查閱一些資料。
methods: { isSearchCityNode(e) { if (!this.$refs.searchCity.contains(e.target)) { console.log("全局事件被觸發(fā)"); this.isLoadCityList = false; } } }, mounted() { document.addEventListener("click", this.isSearchCityNode); }, beforeDestroy() { document.removeEventListener("click", this.isSearchCityNode); }
第四步
需要我們在切換組件的時候保留我們選擇的城市,如果不保留我們每次切換到其他組件時,我們選擇的城市都會被重置為默認(rèn)值,這個體驗肯定是肯差的,也不是我們想要的。
被重置的原因則是我們在每次在不同的組件進(jìn)行切換的時候,組件都會進(jìn)行新建與銷毀,這也會導(dǎo)致重復(fù)渲染問題對性能也是不友好的。
那么我們該如何去處理這個問題呢? 我這里使用了 keep-alive 去解決這個問題,那么 keep-alive 該如何使用以及作用是什么呢?
<keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive>
<keep-alive> 包裹動態(tài)組件時,會緩存不活動的組件實例,而不是銷毀它們,它自身不會渲染一個 DOM 元素,也不會出現(xiàn)在父組件鏈中。
但是當(dāng)我們使用 <keep-alive> 的時候,我們的 beforeDestroy 鉤子函數(shù)就會失效,導(dǎo)致我們第三步的全局事件的解綁就不能執(zhí)行了,原因是我們的組件是被緩存起來,并沒有被銷毀。自然會失效,但是我們并不慌,當(dāng)我們使用 <keep-alive> 時,activated 和 deactivated 兩個鉤子函數(shù)被觸發(fā)。
activated:keep-alive 組件激活時調(diào)用。
deactivated:keep-alive 組件停用時調(diào)用。
所以我們不難發(fā)現(xiàn),我們完全可以使用這兩個鉤子去實現(xiàn)我們?nèi)质录慕壎ㄅc解綁,簡直完美。
activated() { document.addEventListener("click", this.isSearchCityNode); }, deactivated() { document.removeEventListener("click", this.isSearchCityNode); }
總結(jié)
通過一個城市列表組件的案例,介紹了我們在 Vue 中如何綁定全局事件以及進(jìn)行優(yōu)化,一定要記住事件的綁定與解除哪里有一個大坑。
我們通過 <keep-alive> 可以創(chuàng)建一個可以緩存的組件,而且會新增兩個鉤子函數(shù)提供我們使用
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。