Reputation: 121
I'm having some trouble with vue-router. My routes are set up like this:
const routes = [
{ path: '/', component: a },
{ path: '/a', component: a },
{ path: '/b', component: b },
{ path: '/c', component: c }
]
As you can see, I want to load component a
when the page loads. But I don't want the URL to change to /a
when the page loads. However I would like to trigger the router-link-active
-class on the <router-link>
related to the a
component, even though I'm still at /
.
I've tried with some simple JS like:
if(window.location.hash === '#/') {
var el = document.querySelector('#drawerList').firstElementChild;
el.className += 'router-link-active';
}
However vue is not removing the class again when I click on the link to /b
or /c
. Can any of you hint me in the corrent direction?
Upvotes: 2
Views: 4696
Reputation: 3133
use could use exact-active-class
on your router-link element.
Note: desiredClass
is the class you want to apply if the URL matches the router-link's to
attribute.
<router-link to="/about" exact-active-class="desiredClass">About</router-link>
Upvotes: 0
Reputation: 5257
In my case I had a use-case when I needed to have an active class whenever 1 of the following is true:
/users
/users/1/edit
/users/1/view
using vuejs 3
in main app.vue
I have routes defined. The routes are then parameter-injected into sidemenu component
(which is not important in this example)
app.vue
dependencies
import { ref, watch } from "vue";
import { useRoute } from "vue-router";
setup()
method (using composition API
):
setup() {
const route = useRoute();
const myActiveClass = ref(null);
const checkIfMustActivateRoute = () => {
return {
active:
window.location.pathname.startsWith("/users/view/") ||
window.location.pathname.startsWith("/users/edit/"),
};
};
watch(
() => route.fullPath,
async (_) => {
myActiveClass.value = checkIfMustActivateRoute();
}
);
myActiveClass.value = checkIfMustActivateRoute();
const routes = ref([
{ id: 0, name: "Home", href: "/", icon: "fas fa-home" },
{
id: 1,
name: "Users",
href: "/users",
icon: "far fa-clone",
class: myActiveClass,
},
]);
return {
routes,
};
},
NavLink
s are dynamically generated like so:
<li v-for="tab of routes" :key="tab.id" class="nav-item">
<router-link :to="tab.href" class="nav-link" :class="tab.class">
<div class="align-items-center">
<span class="nav-link-icon"><i :class="tab.icon"></i></span>
<span class="nav-link-text ms-3">{{ tab.name }}</span>
</div>
</router-link>
</li>
Now whenever the router's path property changes I trigger the active class update function. This way we don't have to use aliases or any other trickery.
The result is - for all 3 paths I always enable active
class.
Upvotes: 0
Reputation: 550
The best solution is use "exact" in root url
<router-link to="/" tag="a" exact>Home</router-link>
Upvotes: 6
Reputation: 121
This is my pre-answer - see solution instead.
I ended up doing something custom, rather than seeking a native solution. After looking at a few issues on GitHub, I realised that something like this, stupid as it is - I admit, doesn't exist natively in Vue.js.
My solution: adding an eventlistener that removes itself along with the class, once another link is clicked in the #drawerMenu
:
HTML structure:
<ul id="drawerMenu">
<li>
<router-link to="/a">A</router-link>
</li>
<li>
<router-link to="/b">B</router-link>
</li>
<li>
<router-link to="/c">C</router-link>
</li>
</ul>
JS:
if(window.location.hash === '#/') {
var menu = document.querySelector('#drawerMenu');
var el = menu.firstElementChild.firstChild;
el.className += 'router-link-active';
var removeRouterClass = function () {
el.classList.remove('router-link-active');
menu.removeEventListener('click', removeRouterClass);
}
menu.addEventListener('click', removeRouterClass);
}
I hope this helps others like me, and hopefully this will be built into Vue natively at some point.
Upvotes: 0
Reputation: 96
You can manually bind class to router-link like this
<router-link :class="{'router-link-active': $route.fullPath ==='/' || $route.fullPath === '/a'}" to="/a"></router-link>
Upvotes: 8
Reputation: 18156
Try <router-link to="/" exact>
It prevents active class inclusive match behavior.
Upvotes: 0