詳解Vue 動(dòng)態(tài)組件與全局事件綁定總結(jié)
最近在自學(xué) Vue 也了解了一些基本用法,也記錄了一些筆記有興趣的朋友可以去查看我的其他文章,技術(shù)這東西真的不能光靠看,看是沒(méi)有的,你必須要?jiǎng)邮謱?shí)踐,只有在實(shí)戰(zhàn)項(xiàng)目中才能發(fā)現(xiàn)問(wèn)題,才能發(fā)現(xiàn)我們沒(méi)有掌握的知識(shí)點(diǎn),然后發(fā)現(xiàn)問(wèn)題解決問(wèn)題,我們的能力才能得以提升,要不然就有點(diǎn)眼高手低了。
基于這個(gè)想法于是就開始自己去擼了一個(gè)旅游網(wǎng)站,旅游網(wǎng)站嘛避免不了城市的選擇,所以在實(shí)現(xiàn)城市選擇列表的時(shí)候碰到的一些問(wèn)題,以及解決辦法今天就記錄下來(lái)做一個(gè)總結(jié)。
城市列表選擇組件
首先說(shuō)說(shuō)我們要實(shí)現(xiàn)一個(gè)什么樣的城市選擇組件:
- 輸入框獲取焦點(diǎn)時(shí),顯示組件
- 點(diǎn)擊城市列表更新輸入框的城市顯示
- 點(diǎn)擊其他空白處組件隱藏
- 在切換到其他組件時(shí),選擇的城市保留而不是被重置
下面我們就一步一步的來(lái)拆解
第一步
輸入框獲取焦點(diǎn)后顯示組件很簡(jiǎn)單,我們給輸入框綁定焦點(diǎn)事件然后給組件傳入一個(gè)顯示的狀態(tài)即可,我們把 isShowCityList 傳遞給城市選擇組件控制行為。
<el-input @focus="isShowCityList=true" placeholder="請(qǐng)輸入目的地"> </el-input>
第二步
我們也不做過(guò)多的表述本文想更多的是介紹動(dòng)態(tài)組件與全局事件的綁定,利用的是子組件給父組件利用自定義事件 $emit 傳給父組件。
第三步
需要我們?nèi)c(diǎn)擊其他地方城市組件被隱藏,有些同學(xué)的第一印象可能是利用 input 的 blur 事件(就是失去焦點(diǎn)事件),只要我們的 input 失去焦點(diǎn)時(shí),我們就隱藏。
其實(shí)我的第一印象也是如此,但是我們綁定的是 input 的失去焦點(diǎn)事件以后,當(dāng)我們選擇城市列表的時(shí)候也是 input 失去焦點(diǎn)的時(shí)候,所以我們就無(wú)法選取城市。顯然這種思路是不行的。
所以這里我們只能去用到 Vue 的全局事件的綁定,然后去進(jìn)行一個(gè)判斷我們點(diǎn)擊的節(jié)點(diǎn)是哪里,如果是城市組件以外我們就進(jìn)行隱藏操作。
我們?cè)?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)行這一步之后,我們的問(wèn)題得到了解決,只要我們點(diǎn)擊這個(gè)容器以外的地方就會(huì)隱藏城市列表組件,我以為算是結(jié)束了,不過(guò)那是不可能的,還是我太年輕了,這樣做的后果就是不管我們點(diǎn)擊任何一個(gè)地方它都會(huì)觸發(fā)這個(gè)事件,即使是我們切換到其他組件時(shí),事件照樣會(huì)被觸發(fā),顯然這個(gè)不是我們想要的,因?yàn)楫?dāng)前事件會(huì)被無(wú)限觸發(fā),無(wú)疑會(huì)給我們帶來(lái)不可預(yù)見(jiàn)的問(wèn)題。
我們需要的最好效果肯定是當(dāng)前的全局事件就在當(dāng)前的組件下產(chǎn)生作用,當(dāng)我們切換到其他組件時(shí),事件自動(dòng)刪除,于是我可能想到的就是利用 beforeDestroy 鉤子函數(shù)去刪除這個(gè)全局事件。也就是當(dāng)我們切換到其他組件時(shí),去刪除這個(gè)全局事件。
beforeDestroy() { document.removeEventListener("click", () => { //... }); }
你以為這樣我還就能解決問(wèn)題了嗎?顯然還是不能,還是太年輕,只是這樣我們是解除不了綁定的事件,那我們?cè)撛趺崔k呢?其實(shí)這里面有一個(gè)坑,大坑,因?yàn)檫@個(gè)大坑自己不知道,差了許多資料也沒(méi)查出來(lái),因?yàn)椴畹乃悸峰e(cuò)了,最后在一個(gè)群里問(wèn)了一個(gè)大佬,才得出答案,不得不說(shuō)與前輩交流很重要啊,能幫你少踩很多坑。
這里如果想要解除綁定,解除和綁定的兩個(gè)回調(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); }
第四步
需要我們?cè)谇袚Q組件的時(shí)候保留我們選擇的城市,如果不保留我們每次切換到其他組件時(shí),我們選擇的城市都會(huì)被重置為默認(rèn)值,這個(gè)體驗(yàn)肯定是肯差的,也不是我們想要的。
被重置的原因則是我們?cè)诿看卧诓煌慕M件進(jìn)行切換的時(shí)候,組件都會(huì)進(jìn)行新建與銷毀,這也會(huì)導(dǎo)致重復(fù)渲染問(wèn)題對(duì)性能也是不友好的。
那么我們?cè)撊绾稳ヌ幚磉@個(gè)問(wèn)題呢? 我這里使用了 keep-alive 去解決這個(gè)問(wèn)題,那么 keep-alive 該如何使用以及作用是什么呢?
<keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive>
<keep-alive> 包裹動(dòng)態(tài)組件時(shí),會(huì)緩存不活動(dòng)的組件實(shí)例,而不是銷毀它們,它自身不會(huì)渲染一個(gè) DOM 元素,也不會(huì)出現(xiàn)在父組件鏈中。
但是當(dāng)我們使用 <keep-alive> 的時(shí)候,我們的 beforeDestroy 鉤子函數(shù)就會(huì)失效,導(dǎo)致我們第三步的全局事件的解綁就不能執(zhí)行了,原因是我們的組件是被緩存起來(lái),并沒(méi)有被銷毀。自然會(huì)失效,但是我們并不慌,當(dāng)我們使用 <keep-alive> 時(shí),activated 和 deactivated 兩個(gè)鉤子函數(shù)被觸發(fā)。
activated:keep-alive 組件激活時(shí)調(diào)用。
deactivated:keep-alive 組件停用時(shí)調(diào)用。
所以我們不難發(fā)現(xiàn),我們完全可以使用這兩個(gè)鉤子去實(shí)現(xiàn)我們?nèi)质录慕壎ㄅc解綁,簡(jiǎn)直完美。
activated() { document.addEventListener("click", this.isSearchCityNode); }, deactivated() { document.removeEventListener("click", this.isSearchCityNode); }
總結(jié)
通過(guò)一個(gè)城市列表組件的案例,介紹了我們?cè)?Vue 中如何綁定全局事件以及進(jìn)行優(yōu)化,一定要記住事件的綁定與解除哪里有一個(gè)大坑。
我們通過(guò) <keep-alive> 可以創(chuàng)建一個(gè)可以緩存的組件,而且會(huì)新增兩個(gè)鉤子函數(shù)提供我們使用
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- vue3的動(dòng)態(tài)組件是如何工作的
- 詳解vue2.0 使用動(dòng)態(tài)組件實(shí)現(xiàn) Tab 標(biāo)簽頁(yè)切換效果(vue-cli)
- vue 動(dòng)態(tài)組件component
- Vue.js動(dòng)態(tài)組件解析
- vuejs動(dòng)態(tài)組件給子組件傳遞數(shù)據(jù)的方法詳解
- vue 動(dòng)態(tài)組件(component :is) 和 dom元素限制(is)用法說(shuō)明
- Vue 自定義動(dòng)態(tài)組件實(shí)例詳解
- vue動(dòng)態(tài)組件實(shí)現(xiàn)選項(xiàng)卡切換效果
- Vuejs第十二篇之動(dòng)態(tài)組件全面解析
- vue3動(dòng)態(tài)組件使用詳解
相關(guān)文章
Vue el-upload單圖片上傳功能實(shí)現(xiàn)
這篇文章主要介紹了Vue el-upload單圖片上傳功能實(shí)現(xiàn),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-11-11Vue?Router修改query參數(shù)url參數(shù)沒(méi)有變化問(wèn)題及解決
這篇文章主要介紹了Vue?Router修改query參數(shù)url參數(shù)沒(méi)有變化問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09在vue項(xiàng)目中使用element-ui的Upload上傳組件的示例
本篇文章主要介紹了在vue項(xiàng)目中使用element-ui的Upload上傳組件的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02vue3?圖片懶加載的兩種方式、IntersectionObserver和useIntersectionObserve
這篇文章主要介紹了vue3?圖片懶加載的兩種方式、IntersectionObserver和useIntersectionObserver實(shí)例詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03vue使用prop可以渲染但是打印臺(tái)報(bào)錯(cuò)的解決方式
今天小編就為大家分享一篇vue使用prop可以渲染但是打印臺(tái)報(bào)錯(cuò)的解決方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11解決Vue中 父子傳值 數(shù)據(jù)丟失問(wèn)題
這篇文章主要介紹了解決Vue中 父子傳值 數(shù)據(jù)丟失問(wèn)題,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08Vue3.0?axios跨域請(qǐng)求代理服務(wù)器配置方式
這篇文章主要介紹了Vue3.0?axios跨域請(qǐng)求代理服務(wù)器配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04Vue數(shù)據(jù)更新頁(yè)面卻沒(méi)有更新的幾種情況以及解決方法
我們?cè)陂_發(fā)過(guò)程中會(huì)碰到數(shù)據(jù)更新,但是頁(yè)面卻沒(méi)有更新的情況,下面這篇文章主要給大家介紹了關(guān)于Vue數(shù)據(jù)更新頁(yè)面卻沒(méi)有更新的幾種情況以及解決方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06