Day 12:Router 绕去哪-active-class & exact-active-class

上篇我们为 Navbar 设定好路由之後,接下来的需求则是希望能够让选取效果更为明显,优化使用者体验:

  • hover 项目时,字体颜色显示为红色 ⇒ 跟随游标移动位置吸引使用者视线
  • 在被选取的路由底部增加装饰线 ⇒ 便於使用者辨别目前所在的分页位址

改写 BootstrapVue 预设样式

先找到 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;
  }
}

hover

当前路由底部增加装饰线

上篇我们尝试使用两种方式来设定路由,本篇同样依照这两种方式进行相应的处理。一样先在 <b-nav-item> 元件中的 <a> 找到所使用的预设样式如下;但因为预设使用的是 focus 效果,所以只有在初次点击导览项目时才有作用,一旦滑鼠点击其他位置使其失焦时,导览项目便会回到原本的字体颜色。

.navbar-light .navbar-nav .nav-link:focus {
	color: rgba(0, 0, 0, 0.7);
}

1. 透过 router 实例方法 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 到当前位址,所以认为这是多余的导向行为而报错。
redundant navigation

避免重复导向的除错方式有很多种,在此示范两种方式:

  • 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>
    

2. 使用 <router-link> 元件

我们先来观察一下点击导览项目时的编译结果变化。

点击第一个导览项目时:
first nav

点击第二个导览项目时:
second nav

发现了吗?每次被点击的路由都会产生 .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;
    }
  }
}

最後,增加当前路由装饰线的需求也成功解决了!
final

参考资料


<<:  Day-16 雇用问题, 指示器随机变数(indicator random variable), 随机化演算法

>>:  Day_15 Terminal & CLI

[Day2] MacOS - 操作上手

好不容易采购了这个贵松松的东西回来,第一次碰 MacOS 肯定会不知道怎麽操作,马上来研究一下基本功...

Day 5 安装Prometheus

2021 铁人赛 DAY5 昨天已经简单介绍过Prometheus了,今天要来将他装在我们的丛集里,...

自动化初步-使用pyautogui

这个程序是自动开启Google翻译,然後录下Google小姐的声音。 首先一样是先引入模组以及预备,...

Layout, Render 与 View Helper

版型(Layout) 局部渲染(Partial Render) View Helper 在上个章节介...

【Day 8】Cloud x AWS x 李家同教授的最终归宿

tags: 铁人赛 AWS Cloud 概述 碎念时间 今天来玩玩 AWS (Amazon Web ...