vuetify實現Tab多標籤欄,引起的router-link/事件機制問題

寫在前頭

因爲搭建後臺管理系統,國內多采用側邊欄+多標籤切換頁面的方式,故在實現中一樣打算作一個多標籤頁的組件。

↓↓↓↓↓這玩意就是標籤欄,我我的習慣稱爲tabshtml

示例圖

需求描述

  • 點擊側邊欄的某個item,判斷該頁面是否已經打開過前端

    • 沒打開過:vue

      • vue-router自動載入組件,進入頁面
      • 咱們代碼控制,在tabs的數組添加當前新增的這個頁面的路由信息
    • 打開過,切換到對應的tab-item和頁面
  • 點擊不一樣的tab-item實現,頁面的切換(這一步是vue-router自動完成的)
  • 每一個tab-item能夠單獨關閉(首頁不可關閉)
  • 右鍵tabs欄目,顯示context-menuvue-router

    • 可關閉當前:同直接在tab-item上關閉
    • 關閉其餘:保留當前頁和首頁
    • 關閉所有:保留首頁
  • 默認關閉當前tab-item和對應的頁面後,自動跳到前一個tab-item和頁面

遇到的問題

這裏暫時記錄當前遇到的問題,後續如有新坑,再補錄。。

pppp.jpeg

關閉當前tab-item

在基本實現了點擊sidebar-item打開頁面,並在tabs數組中添加新的項後,開始作關閉當前tab-item的功能,可是遇到了坑(灬ꈍ ꈍ灬)。。。vuex

實現思路:後端

  • watch $route的變化,若是新增的tab-item在tabs數組(保存在vuex中)中不存在,就addTabItem()
  • 點擊tab-item的關閉按鈕時,首先判斷關閉的tab-item是否是當前的路由
  • 若是是:數組

    • 從tabs的數組裏刪除掉當前的tab-item
    • 判斷前一個tab-item是否存在
    • 若是存在就router.push到前一個tab-item
  • 若是不是:瀏覽器

    • 直接從tabs數組裏刪除掉那個tab-item

理想的結果:dom

  • 依次點擊t一、t二、t三、t4,分別打開對應的頁面,並在tabs上增長tab-item
  • 點擊tab-item[t4]的關閉按鈕,tabs欄目變爲[t1,t2,t3],頁面自動更新到t3對應的頁面

實際上:異步

  • 點擊tab-item[t4]的關閉按鈕
  • 地址欄一瞬間跳到了t3對應的路由
  • 緊接着又跳回了t4對應的路由
  • watchroute的兩次變化,且在第二的變化中從新在tabs的數組中新增了t4
  • 最終tabs[t1,t2,t3,t4],死循環...

排查思路

  • 首先想,會不會是代碼邏輯的問題,反覆確認,並單獨寫了個簡化版的demo後,肯定邏輯沒有問題
  • 而後想到會不會是vuetify的tabs組件有一些內部的邏輯致使的

    • google搜索了一下,沒有搜到相關問題(主要懷疑在optional這個屬性)
    • 而後又去別人的項目中看了一下,一樣使用的tabs也沒有問題
  • 在參考品別人項目的時候,看到他們都是講邏輯卸載vuex的action

    • 這時候我想 難道是我直接調用mutation出現的問題?
    • 雖然說action支持異步,mutation只能是同步;可是個人router.push邏輯就是寫在mutation刪除當前tab-item以後執行的啊,不可能出現問題啊
  • 而後想會不會是我點擊關閉按鈕的時候,又觸發了tab-item的點擊(close按鈕是包裹在tab標籤裏),事件向上冒泡致使從新載入了當前頁呢?

    • 而後我將關閉當前tab-item按鈕的點擊事件改成@click.stop="onTabClose"
    • 發現然並卵
    • 就排除了這種可能
  • 最後,在不停的對照別人的項目過程當中,發現別人的點擊事件是@click.stop.prevent="onTabClose"

    • 嘗試着增長了.prevent
    • 果真好了,臥槽!!!!!

內心頓時一萬個草尼瑪飄過~~~

456.jpg

在罵本身爲何很少好好看幾遍文檔的時候,忽然意識到,這TM概念我其實知道啊,可是.prevent不是阻止事件默認行爲的麼,勞資實在想不到在這用啊。。。。。。


本着人道主義精神,不能光罵娘,不解決問題啊,因而有了以下:

撥開雲霧見光明:

  • 首先,打開了瀏覽器調試控制檯,經過Vue-DevToos發現,Vuetify的Tab本質上就是一個router-link

image.png

  • router-link的咋就致使出現問題了呢?直接一步到位看看生成的dom是啥吧

image.png

  • 這個是意料之中,就是生成一個a標籤,而後在標籤內包裹着關閉按鈕
  • 那麼問題看樣子就出在這了,既然經過.prevent取消事件的默認行爲來解決問題,那指定是a標籤的默認行爲不守婦道了
  • google了一下,a標籤及其子元素,默認的行爲就是跳轉進入他的href屬性指向的連接
  • 因此爲了一探究竟,專門寫了下面這個demo:
<!DOCTYPE html>

<html lang\="en">

<head>

<meta charset\="UTF-8" />

<meta name\="viewport" content\="width=device-width, initial-scale=1.0" />

<meta http-equiv\="X-UA-Compatible" content\="ie=edge" />

<title>a標籤事件測試</title>

</head>

<body>

<a

id\="waicenga"

href\="[http://www.baidu.com](http://www.baidu.com)"

style\="width: 400px;height:400px;background-color:bisque;display: block"

onclick\="awaiceng(event)"

\>

<button

style\="width: 200px;height:200px;background-color:red"

onclick\="anniu(event)"

\>

這是按鈕

</button>

這是外層

</a>

</body>

  

<script>

// 經過操做dom 監聽click事件,來取消a標籤的默認行爲

document

.querySelector('#waicenga')

.addEventListener('click', function(event) {

// 經過操做dom添加的事件 優先級低於 直接在元素上綁定的onclick

// '外層div事件' -> '測試優先級'

alert('測試優先級')

event.preventDefault()

})

  

// 經過添加event.preventDefault()能夠阻止a標籤的默認行爲

// 可是確點是在點擊事件中對a標籤默認行爲進行的取消

// 經過測試發現:當在anniu()中阻止了冒泡,致使awaiceng()執行不到,進而致使event.preventDefault()沒生效,因此a標籤依然進行了跳轉

// 因此咱們

function awaiceng() {

alert('外層div事件')

// event.preventDefault()

}

  

/\*\*

\*經過測試發現

\* 1. 沒有阻止點擊事件冒泡的狀況下

\* 執行序列: anniu() -> awaiceng() -> 跳轉到百度

\* 2. 添加了事件冒泡後:

\* 執行序列:anniu() -> 跳轉到百度

\*

\* 小結:a標籤內放置的子元素,即便設置了阻止事件冒泡,也不能避免a標籤的默認行爲!!!!!!

\*

\*

\*/

function anniu(event) {

alert('裏面的按鈕的事件')

// event.stopPropagation()

// 在這裏直接阻止a標籤默認行爲也是能夠的

// event.preventDefault()

}

</script>

</html>

小結

  • .stop確實是阻止了冒泡
  • 可是本質上tab內部包裹了一個router-link(其本質是個a標籤)
  • 因此雖然阻止了冒泡,可是a標籤的默認行爲是打開href連接
  • 即便阻止了內部的冒泡,也然並卵
  • 因此最重要的是阻止a標籤的默認行爲

qqqqqqq.jpeg

你說誰TM能想到啊😭,吃一塹長一智把,之後再遇到相似場景的問題,必定要得多注意!!!

寫在結尾

  • 這個問題,折磨我兩天半了,終於也算了卻了一樁心願。。
  • 我這個後端臨時幹前端,果真是遭受了慢慢的惡意
  • 不過仍是怨本身沒有紮實的前端基本功,後面必定得好好系統學習一下前端知識了
  • 以上。
相關文章
相關標籤/搜索