Vue-router: "router-link-active" class is unfriendly with navbar

Created on 19 Aug 2017  ·  12Comments  ·  Source: vuejs/vue-router

What problem does this feature solve?

There are many question about home link (\) always had the "router-link-active" css class.

And the answer always is use exact.

But think about that situation: we have a "topics" nav button, and two paths with one link

/
/page/1
<router-link :to="{ path: '/' }" >Topics</router-link>

Now "router-link-active" will be always actived, looks bad. OK, use the model answer "exact".

<router-link :to="{ path: '/' }" exact>Topics</router-link>

It works fine when path is "/", but not work with path "/page/1"

What does the proposed API look like?

Actually we can use some trick to avoid show wrong highlight style, but I prefer to see vue-router itself works better on it.

BTW: redirect "/" is a solution, but not prefect.

I think add active class with name is a solution:

<router-link :to="{ name: 'topics' }" >Topics</router-link>

Seems active determined by the route's path, whether the route active or not. (version 2.5.3).

Another way is add a new prop, for example:

<router-link :to="{ name: 'topics' }" show-active-if-match="/(^\/$)|(\/page\/(\d+))/">Topics</router-link>

Developers use a regex to match url if they want to handle the class.

The third way (the best i thought):

<router-link :to="{ name: 'topics' }" :active-when="['topic-list', 'topic']">Topics</router-link>
for (let i of active_when) {
    if ($route.name == i) return true;
}
need repro

Most helpful comment

Using exact for the first router-link yields the same result you want (<router-link :to="{name :'topic_list'}" exact>TopicList</router-link>).

If what you want is to have both / highlighted when on /topics/1 but not on /other-page, you'll have to do something custom...

All 12 comments

I don't understand your problem description.

Why should a link to '/' match both '/' and '/page/1'?

@LinusBorg The problem is "router-link-active" class are unfriendly with navbar.
snipaste_20170820_235214
snipaste_20170820_235232

The link match one path, add "router-link-active" css class when match the route name (now it acitved if match the path of RouteConfig)

http://jsfiddle.net/xgrjzsup/3276/
It means text change to red only if $route.name equals to the name inside element.

The second suggestion is that vue-router add "router-link-active" when $route.name match one of several names.

The problem isn't clear to me either. If you could provide a simple jsfiddle showcasing the thing that bothers you, that would help
BTW, you can always manually bind the active class using your own condition

@posva
There is current behavior:
http://jsfiddle.net/xgrjzsup/3277/

Here is what I want:
http://jsfiddle.net/xgrjzsup/3279/

Well, I can manually bind active classes regardless of css classes auto added by vue-router.
But I prefer to use \ Don't you think usage of "router-link-active" is very limited now?

Using exact for the first router-link yields the same result you want (<router-link :to="{name :'topic_list'}" exact>TopicList</router-link>).

If what you want is to have both / highlighted when on /topics/1 but not on /other-page, you'll have to do something custom...

@posva
This example is about why not use exact.
http://jsfiddle.net/k11c8wsc/1/

The problem is "router-link-active" usually need to be replaced by custom code.
I don't know the origin purpose of "router-link-active", but I think it's not very useful now.
So I ask for adding a \ attr/directive(or using name match instead of path match) to improve this situation.

Usually, you have some kind of prefix for that kind of routes: /items/:id, and in that case, you won't need exact. I haven't analyzed your path /:p(p)?/:page(\\d+)? but TopicList should be highlighted when using exact

@posva
The path looks strange because I want to make / and /p/1 show the same page and use same RouteConfig, but it's not the point.

You can noticed in this case, Topics hightlighted when path is /, /p/1 or /topic/1. Actually two routes named topic_list and topic.
Just like both /vuejs/vue-router/pull/1687 and /vuejs/vue-router/pulls highlights the Pull requests button.
http://jsfiddle.net/xgrjzsup/3279/

maybe you say because of the version problem 1.0 and 2.0

Seems that / matches all routes and setting the active class. When maybe it should be * that matches all. / matching all routes is frustrating when your integrating in to another backend that uses the root for a specific view. One other problem is that the search query is also taken in to consideration for matches which can be annoying if you want to persist a query string to another route but might not always be provided.

https://codesandbox.io/s/kwl495v077
However I was able to circumvent the problems with / matching all routes by using redirects in the config to ensure nothing is on the root path.

Using exact for the first router-link yields the same result you want (<router-link :to="{name :'topic_list'}" exact>TopicList</router-link>).

If what you want is to have both / highlighted when on /topics/1 but not on /other-page, you'll have to do something custom...

Adding "exact at the end of router-link" fixed my issue!


Thanks a lot!

Emmmmmmmm, I remembered this issue was closed. The problem was solved to me for a long time.

Was this page helpful?
0 / 5 - 0 ratings