Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
FreekVR opened this issue Jul 21, 2022 · 9 comments

Comments

@FreekVR
Copy link

FreekVR commented Jul 21, 2022

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)

@BrankoKrstic
Copy link

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.

@gianpesto
Copy link

gianpesto commented Oct 18, 2022

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
Copy link

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.

@Phyllon
Copy link

Phyllon commented Nov 24, 2022

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

@al-amiir
Copy link

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 "^^

@danielroe danielroe added the 2.x label Jan 18, 2023
@seriouslysean
Copy link

seriouslysean commented Jan 21, 2023

I ran in to a similar issue on our vue@2.7.14 app with vue-router@3.6.5. 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

@notorigine
Copy link

Any work-around while this gets fixed? 👀

@k-utsumi
Copy link

k-utsumi commented Feb 8, 2023

#10593 (comment) 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>

@danielroe
Copy link
Member

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: vuejs/vue#12781.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants