I use this navbar. And it's ok when href links are different. But when two pages have the same link, active class appears for both li with that link in the way I write.
Vue.component('navbar', {
template: `<svg xmlns="http://www.w3.org/2000/svg" width="15.352" height="15.355" viewBox="0 0 15.352 15.355">
<path id="Union_19" data-name="Union 19" d="M-19.5-15958.5l-7.5,7.5,7.5-7.5-7.5-7.5,7.5,7.5,7.5-7.5-7.5,7.5,7.5,7.5Z" transform="translate(27.176 15966.178)" fill="none" stroke="#bbb" stroke-width="0.5"/>
</svg>`
})
new Vue({
el: "#app",
data() {
return {
menu: [
{ to: { name: 'link1' }, name: 'page1' },
{ to: { name: 'sameLink' }, name: 'page2' },
{ to: { name: 'sameLink' }, name: 'page3' },
{ to: { name: 'link2' }, name: 'page4' }
]
}
}
});
.nav {
display: flex;
flex-wrap: nowrap;
margin-bottom: 0;
list-style: none;
font-size: .875rem;
overflow: auto;
background-color: $navBar-bg;
}
.navLink {
display: block;
color: $navBar-color;
text-decoration: none;
position: relative;
white-space: nowrap;
@include hover-focus() {
text-decoration: none;
color: $navBar-hover-color;
}
&.disabled {
color: $navBar-disabled-color;
pointer-events: none;
cursor: default;
}
:global(.show) > &,
:global(.active) > &,
.nav-link:global(.show),
.nav-link:global(.active) {
color: red;
&:after {
content: '';
display: block;
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: .1875rem;
background-color: currentColor;
}
}
}
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap@4.5.3/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.css" />
<script src="https://unpkg.com/vue@2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue@2.21.2/dist/bootstrap-vue.min.js"></script>
<div id="app">
<ul class="nav">
<router-link
v-for="{ to, name } in menu"
v-slot="{ href: linkHref, navigate, isActive, isExactActive }"
:key="to.name || name"
:to="to"
>
<li v-else :class="['nav-item', isActive && 'active', isExactActive && 'exact-active']">
<a
v-t="name"
href="linkHref"
class="navLink"
/>
</li>
</router-link>
</ul>
</div>
How can I have sameLink for pages but be active on only the page is shown and really active? These pages are different in content because of some filters but both have the same link.
The properties isActive
and isExactActive
will be the same for router-links that point to the same route, which is the case for menu items page2
and page3
in your example. You could define these as different routes pointing to the same router-view component
const routes = [
{ name: 'page2', path: '/foo', component: Foo },
{ name: 'page3', path: '/foo', component: Foo }
]
and then compare the current route name to the route name of each link to determine the exact active class:
<div id="app">
<ul class="nav">
<router-link
v-for="{ to, name } in menu"
v-slot="{ href: linkHref, navigate, isActive, isExactActive }"
:key="to.name || name"
:to="to"
>
<li v-else :class="['nav-item', isExactActive && $route.name === name && 'exact-active']">
<a
v-t="name"
href="linkHref"
class="navLink"
/>
</li>
</router-link>
</ul>
</div>