Vue在chrome44偶現(xiàn)點(diǎn)擊子元素事件無法冒泡的解決方法
前言
公司的一個項(xiàng)目大致是這樣的:一個左側(cè)列表,點(diǎn)擊左側(cè)列表的文章標(biāo)題,右側(cè)展開該文章對應(yīng)的內(nèi)容的。
現(xiàn)在的問題出現(xiàn)在極少部分客戶有時左側(cè)的標(biāo)題,無法打開對應(yīng)的右側(cè)的內(nèi)容,給人的改進(jìn)就是‘卡'、點(diǎn)不動、點(diǎn)了沒反應(yīng)。
再大致介紹下項(xiàng)目環(huán)境:
chrome 44(打包到用戶客戶端內(nèi))
Vue 2.6.10
左側(cè)列表布局
列表的每個綠色方框是一個vue組件,名叫ListItem,列表的組件叫List
代碼類似這樣
// List.vue <template> <div class="blue"> <list-item v-for="item in dataList" :data="item" @click="handleClick"> </div> </template> <script> export default { ... methods: { handleClick() { ... 請求文章內(nèi)容相應(yīng)的邏輯 } } } </script>
// ListItem.vue <template> <div class="green" @click="onClick"> <div class="red circle"></div> <div class="red square"> <div class="yellow square1"></div> <div class="yellow square2"></div> </div> </div> </template> <script> export default { ... methods: { onClick(e) { console.log('點(diǎn)擊', e.target); this.$emit('click'); } } } </script>
首先大家不要評論這個click是不是多此一舉,為什么不直接在Lisit.vue里面寫@click.native="handleClick"
。原項(xiàng)目就是這樣寫的,其中的部分邏輯我簡化了,最重要的是這個不是我們討論的重點(diǎn)。
根據(jù)上面的代碼我們只要在綠色的方框內(nèi)點(diǎn)擊,均可以實(shí)現(xiàn)請求文章內(nèi)容。實(shí)測也是沒有問題的,但是上線以來,有部分用戶報(bào)障“文章列表點(diǎn)不動(其實(shí)就是onClick -> handleClick
沒有調(diào)用”,作為開始說實(shí)話一開始是不信,這么簡單的邏輯,這時vue的常規(guī)操作好嗎,怎么可能有問題。
但是經(jīng)過遠(yuǎn)程和實(shí)地確認(rèn),確實(shí)是有這樣的問題。
經(jīng)過調(diào)查發(fā)現(xiàn),當(dāng)點(diǎn)擊上圖紅色圓圈下方時,是可以觸發(fā)onClick的。其實(shí)此時是剛好直接點(diǎn)到綠方框這個元素了,也就是說我們直接點(diǎn)到綁定了點(diǎn)擊事件的div上時是可以觸發(fā)onClick。我們的第一反應(yīng)是這<div class="green">的子元素是否使用了阻止冒泡,可惜沒有,如果有,開發(fā)自測和測試人員測試早就會發(fā)現(xiàn),該問題不可能到線上才被發(fā)現(xiàn)。
我們有懷疑是除了click以外其他事件的影響,比如mousedown、mouseup被阻止冒泡,是否存在使用事件捕獲并且還阻止冒泡的情況,經(jīng)過排除后,發(fā)現(xiàn)是有一部分的,按照寧愿錯殺不能漏殺的原則,我們針對這些事件都進(jìn)行調(diào)整,但是是否真的解決了這個問題,我們不知道,因?yàn)檫@個問題我們開發(fā)人員本地、測試人員在測試環(huán)境和生產(chǎn)環(huán)境均無法復(fù)現(xiàn)。每次只能在發(fā)版的時候帶上去一點(diǎn)點(diǎn)改動,改動的前提是不保證能改好,但是一定不會改壞,面對客戶的報(bào)障我們只能叫他們用臨時的解決方案,也是點(diǎn)擊紅色圓圈下面那塊區(qū)域。
有一次我們增加了在紅色圓圈和紅色方框上綁定同一個事件,也就是
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <script> (adsbygoogle = window.adsbygoogle || []).push({ google_ad_client: "ca-pub-3013839362871866", enable_page_level_ads: true }); </script>
// ListItem.vue <template> <div class="green" @click="onClick"> <div class="red circle" @click="onClick"></div> <div class="red square" @click="onClick"> <div class="yellow square1"></div> <div class="yellow square2"></div> </div> </div> </template>
是的,我們就差在<div class="yellow square1">
和<div class="yellow square2">
也綁上點(diǎn)擊事件了。我們太難了。。。
這樣上線后依然有問題,大家應(yīng)該料到了,如果那些用戶點(diǎn)到了
<div class="yellow square1">
和<div class="yellow square2">
上依然是無法觸發(fā)onClick的,作為一個程序員,我們絕不容忍在每個div上綁定同樣的事件啊,我們放棄了這樣的改動,做個有尊嚴(yán)的程序員,不是嗎?
在用戶發(fā)生“點(diǎn)不動”的時候,我們實(shí)體去看的時候發(fā)現(xiàn):
1.我們在調(diào)試工具里面將所有的dom上綁定的事件都移除,只保留自己綁定的<div class="green" @click="onClick">這一個事件,用戶依然“點(diǎn)不動”,依然只有點(diǎn)擊紅圈才能觸發(fā)onClick。
2.我們在控制臺使用document.querySelect('.yellow .square1').click()的方式是可以觸發(fā)onClick的,也就是該點(diǎn)擊事件其實(shí)是可以冒泡到<div class="green">的。
為什么我們用鼠標(biāo)點(diǎn)擊就不行了,并且通過在控制打印出我們點(diǎn)擊的元素,我們可以100%確定我們用鼠標(biāo)點(diǎn)擊的就是document.querySelect('.yellow .square1')
所對應(yīng)的這個元素。
這個發(fā)現(xiàn)完全顛覆了我們的認(rèn)知。到底是哪里錯了,要么是Vue,要么是瀏覽器,都是大佬啊,它們錯了?其他人都在用,都沒毛病啊,并且這個問題無法復(fù)現(xiàn),沒有必現(xiàn)流程,使用按鍵精靈模擬用戶操作了一天也沒有復(fù)現(xiàn)。怎么跟其他人,大家只會覺得你連這么簡單的問題都搞不定?代碼也給很多前端同事、前端大佬review過了,沒毛病啊。但是生產(chǎn)上就是有人使用時會出現(xiàn)“點(diǎn)不動”,這是事實(shí)啊。
瀏覽器是前端的根基,我們我只能開始大膽懷疑下是Vue的問題,或者我們的用法有問題(怎么用沒有問題),或者說這個版本的Vue在這個版本的Chrome44在部分場景中有問題。
搜了vue event propagation相關(guān)的內(nèi)容,有一點(diǎn)小小的發(fā)現(xiàn),之前確實(shí)有人反映過Vue 2.4.2在子元素事件冒泡相關(guān)的issue,并且vue的源碼里面也有相關(guān)的注釋。
雖然上面提到的 #6566 issue并非跟我們的問題一模一樣,但是既然有個提過這類bug,我們更有里有相信可能是Vue的問題(或者說我們用的不對)了
最后我們決定放棄這個用Vue寫的點(diǎn)擊事件的寫法,改用jQuery了。
在上面列表的<div class="blue"></div>
上綁定事件,然后根據(jù)對應(yīng)的文章id來實(shí)現(xiàn)打開對應(yīng)文章的目的,這一部分沒什么技術(shù)含量,就不細(xì)說了。
是的,最終我們放棄了尋找這個問題的原因了,面對用戶的頻繁報(bào)障,再加上我們無法復(fù)現(xiàn)問題,根本不知道改好了沒有,我們也不可能頻繁發(fā)版在生產(chǎn)上讓用戶幫我們測試(測試人員第一個不答應(yīng))。
這個到底解決好了沒有,從理論上應(yīng)該是沒問題了,但是我們說了不算,就看客戶還有沒有這樣的報(bào)障了,畢竟得靠他們來驗(yàn)證。
一個靈異問題從入門到放棄,我們終于把Vue徹底用成了我們討厭的樣子。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對腳本之家的支持。
相關(guān)文章
Vue.js實(shí)現(xiàn)的表格增加刪除demo示例
這篇文章主要介紹了Vue.js實(shí)現(xiàn)的表格增加刪除demo,結(jié)合實(shí)例形式分析了vue.js數(shù)據(jù)綁定及元素增加、刪除等相關(guān)操作技巧,需要的朋友可以參考下2018-05-05關(guān)于Element-ui中table默認(rèn)選中toggleRowSelection問題
這篇文章主要介紹了關(guān)于Element-ui中table默認(rèn)選中toggleRowSelection問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08vue+element tabs選項(xiàng)卡分頁效果
這篇文章主要為大家詳細(xì)介紹了vue+element tabs選項(xiàng)卡分頁效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09Vue3.0插件執(zhí)行原理與實(shí)戰(zhàn)
這篇文章主要介紹了Vue3.0插件執(zhí)行原理與實(shí)戰(zhàn),Vue項(xiàng)目能夠使用很多插件來豐富自己的功能Vue-Router、Vuex等,節(jié)省了我們大量的人力和物力,下面我們就一起來了解Vue3.0插件的原理吧,需要的小伙伴可以參考一下2022-02-02vue中的模態(tài)對話框組件實(shí)現(xiàn)過程
這篇文章主要介紹了vue中的模態(tài)對話框組件實(shí)現(xiàn)過程,通過template定義組件,并添加相應(yīng)的對話框樣式,需要的朋友可以參考下2018-05-05vue-resource調(diào)用promise取數(shù)據(jù)方式詳解
這篇文章主要介紹了vue-resource調(diào)用promise取數(shù)據(jù)方式詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07vue3+vite項(xiàng)目中顯示SVG圖片的實(shí)現(xiàn)
vite-plugin-svg-icons是一個Vite插件,其作用是將SVG圖標(biāo)文件轉(zhuǎn)換為Vue組件,本文主要介紹了vue3+vite項(xiàng)目中顯示SVG圖片的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02