5

I have a <router-link /> that I want to use to navigate to another page in a Vue 3 application, but I also want to run another function when this link is clicked.

Right now I have to use an extra <span /> element to wrap the <router-link /> and add the @click attribute there to rely on event bubbling. Adding the @click handler on <router-link /> causes the router link not to work and the browser thinks it is just a normal anchor href.

    <span @click="handleClose(imageId)">
      <router-link
        :to="{name: 'image', params: {'imageId': imageId}}"
        class="permalink">
        Permalink
      </router-link>
    </span>

Is there a better way?

1

2 Answers 2

5

To avoid potential weird concurrency bugs (the view change could happen before your method being called, method which would then be attached to an unmounted component), I would do a programmatic navigation in your method:

<template>
  <button type="button" @click="handleClose(imageId)">
    Permalink
  </button>
</template>

<script>
import router from '@/wherever/your/router/is/initialized';

export default {
  methods: {
    handleClose(imageId) {
      // Do your stuff
      router.push({ name: 'image', params: {'imageId': imageId}});
    }
  }
}
</script>
Sign up to request clarification or add additional context in comments.

2 Comments

I need the anchor link as people might copy the permalink.
strugling with same thing, seems this is only way
4

You must use the .native modifier on the @click event of router-link. The reason is quite simple - router-link is a Vue component but it does not emit a click event. Therefore you have to listen for the native click event coming from the browser.

https://github.com/vuejs/vue-router/issues/800

var router = new VueRouter({
routes:
[
{path: '/', component: {
template: '#first',
methods:
{
  showAlert(text)
  {
    window.alert(text);
  }
}
}},
{path: '/second', component: {
template: '#second',
methods:
{
  showAlert(text)
  {
    window.alert(text);
  }
}
}},
]
});
new Vue(
{
template: '#main',
router: router,
}).$mount('#app');
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">test</div>
<template id="main">
<div>
<router-view></router-view>
</div>
</template>
<template id="first">
<router-link to="/second" @click.native="showAlert('second')">GOTO second</router-link>
</template>
<template id="second">
<router-link to="/" @click.native="showAlert('first')">GOTO first</router-link>
</template>

5 Comments

It actually does emit the click event. And as in the first answer, both @click and @click.native resulted in the same behaviour, so neither worked. Only the span trick worked.
@click.native works just fine, as you can see if you run the code snippet above.
vue3 removed .native, this will not compile
@JiroMatchonson Can you provide a link to the official documentation, where the removal of .native is documented?
I'm using vue-router 3.2.0 and this answer worked for me where @click did not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.