Vue router-link 匹配忽略 query string

Lastor
Code 隨筆放置場
4 min readApr 2, 2020

實作 Vue router-link,希望幫當前 link 添加 active 樣式時碰到了點問題。這邊稍微紀錄一下。

畫面上有兩組 menu,上方是主 menu,使用 Bootstrap 的 Nav Tabs 樣式。
下方是隸屬於「首頁」的子 menu,使用 Bootstrap 的 Nav Pills 樣式。

使用 Vue 的 router-link 來製作超連結時,Vue 會自動幫我們在當前的 link 上添加 active 用的 class,讓我們可以簡單的製作 active 按鈕樣式。

其中,active class 在 Vue 裡面被分為兩種:
1. 包含匹配,active-class
2. 完全匹配,exact-active-class (簡稱 exact)

例如,點擊上圖的「最新動態」,當前路由會是 /restaurants/feeds,「最新動態」上面就會被 Vue 添加一個叫做 router-exact-link-active 的 class。同時也會被添加 router-link-active 這個 class。

而「首頁」的路由有包含到了 /restaurants,所以「首頁」也會被添加上 router-link-active 這個 class,但是不會出現 exact。

Vue 提供了一些設定,讓我們可以變更這兩種 class 的預設名稱。我們就可以把完全匹配的 exact 更名成 Bootstrap 的樣式名 active,就能自動套上樣式了。

Vue 的 router-link 設計簡單介紹完,接著來進入正題。先回顧這張圖。

由於下方的子 menu 是隸屬於「首頁」這個 link,自然我們會期待,當點擊「中式料理」or 「日式料理」這些分類時,上面「首頁」的 active 特效也應該保持著。

但現實卻不如人意。

首頁的 active 消失,是由於下方的分類有夾帶 query string,而 exact 要求的是「完全匹配」,導致 exact-active-class 沒有被添加上去。

最開始的想法,是去尋找 Vue 有沒有一些設定,可以忽略 query string。但苦尋半天似乎沒有。只在 Github 上找到了相關的 issues

裡面有提到一個比較直接的做法,就是徒手直接寫判定,去添加 class。
以此為延伸,這邊我想到兩種解法:

1. 直接對 class active 寫判定,
當 tab 是「首頁」且路由也位在 “restaurants” 時,添加 active。

:class="{
active: (tab.title === '首頁') && ($route.name === 'restaurants')
}"
// 註: tab 是從 tabs 陣列 v-for each 出來的 data

2. 利用包含匹配的 active-class,
點選了下方的分類選項之後,雖然「首頁」的 exact 匹配失敗,但是另一個 active-class 是有被添加上去的。於是就有了操作空間。

:active-class="($route.name === 'restaurants') ? 'active' : '' "

當 route 位在 restaurants 時,將名為 active 的 active-class 添加上去。

如此便能實現固定主 menu active 特效的需求了。

--

--

Lastor
Code 隨筆放置場

Web Frontend / 3D Modeling / Game and Animation. 設計本科生,前遊戲業 3D Artist,專擅日本動畫與遊戲相關領域。現在轉職為前端工程師,以專業遊戲美術的角度涉足 Web 前端開發。