nuxt icon indicating copy to clipboard operation
nuxt copied to clipboard

@click listener on <nuxt-link> or <router-link> no longer works inside page components on Vue 2.7

Open FreekVR opened this issue 1 year ago • 6 comments

Versions

  • nuxt: 2.15.8
  • vue: 2.7.7 (also 2.7.x other versions)
  • node: 14

Reproduction

https://codesandbox.io/s/happy-mendeleev-2klf2i?file=/pages/index.vue

Additional Details
Works in Vue 2.6, given the following page component
<template>
  <div>
    Hello world!
    <ul>
      <li>
        <nuxt-link to="/bar" @click.native="showLog">
          Should alert, but does not
        </nuxt-link>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  methods: {
    showLog() {
      alert("Does not show!");
    },
  },
};
</script>

Steps to reproduce

Upgrade an existing Nuxt 2 app to Vue 2.7 or create a new one.

@click.native handlers on nuxt or router links no longer function as they did in 2.6, but apparently only broke in page components or children thereof. They work fine when put directly in layout. It seems like the click handler is no longer executed before the page component gets destroyed, or something else might have changed. I could not reproduce the same issue using Vue-Router 3.5.4 on a non-Nuxt Vue 2.7 app. The interesting thing is that click.prevent or click.native.prevent also do not prevent a route change, but I did not test if this ever even worked in 2.6.

What is Expected?

The event handler is executed

What is actually happening?

The event handler is only executed some times (in layout, see repro)

FreekVR avatar Jul 21 '22 13:07 FreekVR

Same issue here on Node 16.16.0; Updating from Vue 2.6.14 to 2.7.8 breaks the native click handlers.

The handlers also seem to work fine when there is no navigation, e.g. when a NuxtLink leads to the current route. Seemingly navigation cancels handler execution.

BrankoKrstic avatar Jul 28 '22 22:07 BrankoKrstic

having the same problem as i wondered why all the sudden my app was behaving strange. ended up wrapping the slot in a span and adding the click-handler to it instead of binding it to nuxt-link.

edit: Also my wokaround doesn't really always work that great

gianpesto avatar Oct 18 '22 14:10 gianpesto

I also could narrow down that this problem only pops up if the click on nuxt-link is referring to a page with a different layout than the current page.

gianpesto avatar Oct 18 '22 15:10 gianpesto

Please refer to https://stackoverflow.com/a/74561723/19901666 for Nuxt3.

Phyllon avatar Nov 24 '22 13:11 Phyllon

Hello, For me, it is still not working But, here is a quick solution Instead of using the navigation from the NuxtLink component Use any other tag like button, div ...etc, then Inside the "handle" function, navigate by typing: this.$router.push("/about")

Before:

            <NuxtLink  @click="handler"  to="/about" > About Page </NuxtLink>

After:

            <button  @click="handler" > About Page </button>

into the handler function:

/// do something 
this.$router.push("/about")

Now you can do what you want and then navigate, Hope this quick fix helps "^^

al-amiir avatar Dec 12 '22 10:12 al-amiir

I ran in to a similar issue on our [email protected] app with [email protected]. We do not use Nuxt (but have looked in to it) and this issue is spot on to what I noticed. A bunch of the analytics calls we fire live on a router-link and get merged down from a functional parent component.

I put together a Nuxt 2 example, and added a solve that should work for most people. It's a little more work up front, but should make the whole process relatively invisible once you implement it.

Instead of doing programmatic navigation, you can create a wrapper component and just proxy the click events to an inner element (like a span) and let event bubbling handle the priority. By doing this, your events will fire first, and then the route operation will take place.

Something like this:

<template>
  <NuxtLink v-bind="$attrs"> <!-- bind attrs like class, etc to the root -->
    <span v-on="$listeners"> <!-- bind listeners to this inner element -->
      <slot />
    </span>
  </NuxtLink>
</template>

<script>
export default {
  name: 'BaseLink',
  inheritAttrs: false, // prevent events from binding to the root element
};
</script>

Reproduction on StackBlitz, https://stackblitz.com/edit/nuxt-starter-aaaqgu?file=components/Navigation.vue

click-event-bubbling

seriouslysean avatar Jan 21 '23 01:01 seriouslysean

Any work-around while this gets fixed? 👀

notorigine avatar Jan 21 '23 18:01 notorigine

https://github.com/nuxt/nuxt/issues/10593#issuecomment-1399109931 does not seem to correspond to key operation. Focusing on Home and pressing enter does not work.

<template>
  <NuxtLink v-bind="$attrs"> <!-- bind attrs like class, etc to the root -->
    <span v-on="$listeners"> <!-- bind listeners to this inner element -->
      <slot />
    </span>
  </NuxtLink>
</template>

Maybe we can do it this way.

<template>
  <a
    href="/path-to-another-layout-page"
    @click="
      (e) => {
        if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
  
        e.preventDefault();
        $router.push('/path-to-another-layout-page');
      }
    "
  >
    Another layout page
  </a>
</template>

k-utsumi avatar Feb 08 '23 18:02 k-utsumi

As pointed out above - thanks for the very helpful investigation! - this is not a Nuxt issue but a change in Vue 2.7 or Vue Router. Would you raise an issue upstream in one of those repos? Possibly linked: https://github.com/vuejs/vue/issues/12781.

danielroe avatar Feb 08 '23 19:02 danielroe