上篇我們為 Navbar 設定好路由之後,接下來的需求則是希望能夠讓選取效果更為明顯,優化使用者體驗:
先找到 BootstrapVue 在 <b-nav-item> 元件中的 <a> 有使用了預設樣式如下:
.navbar-light .navbar-nav .nav-link:hover {
color: rgba(0, 0, 0, 0.7);
}
再改成專案所需的紅色字體即可,留意權重需蓋過預設樣式。(.my_navbar
是在 Navbar 元件最外層 <b-navbar> 所加的自定義 class name,與 BootstrapVue 預設的 .navbar-light
同層)
.my_navbar {
&.navbar-light .navbar-nav .nav-link:hover {
color: red;
}
}
上篇我們嘗試使用兩種方式來設定路由,本篇同樣依照這兩種方式進行相應的處理。一樣先在 <b-nav-item> 元件中的 <a> 找到所使用的預設樣式如下;但因為預設使用的是 focus 效果,所以只有在初次點擊導覽項目時才有作用,一旦滑鼠點擊其他位置使其失焦時,導覽項目便會回到原本的字體顏色。
.navbar-light .navbar-nav .nav-link:focus {
color: rgba(0, 0, 0, 0.7);
}
router.push()
透過觸發 click
點擊事件後,再指定要導向 route name 為 navItem.name
的位址。
<b-navbar-nav
class="my_navbar_item"
v-for="navItem in navList"
:key="navItem.id"
>
<b-nav-item href="#" @click="$router.push({ name: navItem.name })">
{{ navItem.item }}
</b-nav-item>
</b-navbar-nav>
因為裝飾線只需要加在目前路由上,所以我們為 <b-nav-item> 綁定一個寫好裝飾線樣式的 class name,透過 v-bind
的陣列語法,並利用「條件(三元)運算子」來完成條件綁定,其條件是當目前路由與點擊事件所導向的位址相同時,該 <b-nav-item> 才會產生名為 current_route
的 class,如此一來就能避免同時為所有的 <b-nav-item> 產生裝飾線樣式。
<b-nav-item
href="#"
@click="$router.push(navItem.name)"
:class="[$route.name === navItem.name ? 'current_route' : '']"
>
{{ navItem.item }}
</b-nav-item>
不過,使用 router.push()
需要特別留意一點,就是當你重複點擊相同路由時,DevTools 會立馬出現錯誤訊息「"NavigationDuplicated: Avoided redundant navigation to current location"」,因為對瀏覽器而言,它已經在當前位址了,搞不懂為什麼還要再 push 到當前位址,所以認為這是多餘的導向行為而報錯。
避免重複導向的除錯方式有很多種,在此示範兩種方式:
catch error 捕獲錯誤,但不用特別處理錯誤
<b-nav-item
href="#"
@click="$router.push(navItem.name).catch(error => error)"
:class="[$route.name === navItem.name ? 'current_route' : '']"
>
{{ navItem.item }}
</b-nav-item>
使用 router.push(location, onComplete?, onAbort?)
第三個參數,當路由切換失敗時才會執行onAbort
callback function。
<b-nav-item
href="#"
@click="$router.push({ name: navItem.name }, () => {}, (error) => error)"
:class="[$route.name === navItem.name ? 'current_route' : '']"
>
{{ navItem.item }}
</b-nav-item>
<router-link>
元件我們先來觀察一下點擊導覽項目時的編譯結果變化。
點擊第一個導覽項目時:
點擊第二個導覽項目時:
發現了嗎?每次被點擊的路由都會產生 .router-link-exact-active
和 .router-link-active
的 class!
這兩個 class 其實分別是 <router-link>
props 中 exact-active-class 及 active-class 的預設值,前者代表精準(exact)比對出當前路由,後者則為模糊比對當前路由,因此可以利用這兩個既有的 class 屬性,直接設定我們所需要的裝飾線樣式即可。
回頭參考 App.vue,也是在 <style> 中對 .router-link-exact-active
設定樣式,使得當前路由在 Home 或 About 時會呈現綠色字體,就是這麼回事!
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
最後,增加當前路由裝飾線的需求也成功解決了!