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

The default click listener added by the router.ts level is too high #4075

Closed
4 tasks done
shellRaining opened this issue Jul 25, 2024 · 3 comments
Closed
4 tasks done
Labels

Comments

@shellRaining
Copy link
Contributor

Describe the bug

I've been trying to add a view transition effect to the article links on the homepage recently, I saw such a display effect.

bug_report.mp4

When I first clicked on the article link, the transition effect displayed normally. After clicking the same article link a second time, could see the article flicker for a moment.

Reproduction

The link below is my relevant code, which is very simple, containing only a template for an "a" link, and then there is a click event listener that executes a transition effect upon clicking.

https://github.com/shellRaining/blog/blob/main/theme/Home/PostItem.vue

After my investigation, I found that an event listener was at too high a level, preventing me from intercepting its actions.

window.addEventListener(
'click',
(e) => {
if (
e.defaultPrevented ||
!(e.target instanceof Element) ||
e.target.closest('button') || // temporary fix for docsearch action buttons
e.button !== 0 ||
e.ctrlKey ||
e.shiftKey ||
e.altKey ||
e.metaKey
)
return
const link = e.target.closest<HTMLAnchorElement | SVGAElement>('a')
if (
!link ||
link.closest('.vp-raw') ||
link.hasAttribute('download') ||
link.hasAttribute('target')
)
return
const linkHref =
link.getAttribute('href') ??
(link instanceof SVGAElement ? link.getAttribute('xlink:href') : null)
if (linkHref == null) return
const { href, origin, pathname, hash, search } = new URL(
linkHref,
link.baseURI
)
const currentUrl = new URL(location.href) // copy to keep old data
// only intercept inbound html links
if (origin === currentUrl.origin && treatAsHtml(pathname)) {
e.preventDefault()
if (
pathname === currentUrl.pathname &&
search === currentUrl.search
) {
// scroll between hash anchors in the same page
// avoid duplicate history entries when the hash is same
if (hash !== currentUrl.hash) {
history.pushState({}, '', href)
// still emit the event so we can listen to it in themes
window.dispatchEvent(
new HashChangeEvent('hashchange', {
oldURL: currentUrl.href,
newURL: href
})
)
}
if (hash) {
// use smooth scroll when clicking on header anchor links
scrollTo(link, hash, link.classList.contains('header-anchor'))
} else {
window.scrollTo(0, 0)
}
} else {
go(href)
}
}
},
{ capture: true }
)

I attempted to intercept this event by using the capture and stopImmediatePropagation functions, but due to the timing of the setup being relatively late, it was not possible to achieve this. When I replaced the a link with button, this bug no longer occurred.

Expected behavior

I hope to adjust the hierarchy of this listener so that users can customize link jump behavior.

System Info

System:
    OS: macOS 14.1
    CPU: (8) arm64 Apple M1
    Memory: 78.14 MB / 8.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.4.1 - /opt/homebrew/bin/node
    Yarn: 1.22.22 - /opt/homebrew/bin/yarn
    npm: 10.8.1 - /opt/homebrew/bin/npm
    pnpm: 9.6.0 - ~/Library/pnpm/pnpm
    Watchman: 2024.07.15.00 - /opt/homebrew/bin/watchman
  Browsers:
    Safari: 17.1
    Chrome: upon 111

Additional context

Is there any other way to solve this problem? I once wanted to use onBeforeRouteChange hook, but seems not suit my requirement.

Validations

@shellRaining shellRaining added the bug: pending triage Maybe a bug, waiting for confirmation label Jul 25, 2024
@brc-dd
Copy link
Member

brc-dd commented Jul 25, 2024

In your case, since you are manually handling routing, you can add something like this to completely skip the router:

const viewTransitionsEnabled = ref('false')
onMounted(() => {
  viewTransitionsEnabled.value = 'startViewTransition' in document
})

<a
  :class="viewTransitionsEnabled && 'vp-raw'"
  ...
>

@shellRaining
Copy link
Contributor Author

<script lang="ts" setup>
const viewTransitionsEnabled = ref(false);
onMounted(() => {
  viewTransitionsEnabled.value = "startViewTransition" in document;
});
</script>


<template>
  <a
    class="post-title"
    :class="viewTransitionsEnabled && 'vp-raw'"
    :href="withBase(post.url)"
    @click="changeRoute(post.url)"
  >
    {{ post.frontmatter.title }}
  </a>
</template>

still not work, and an error has occurred Hydration completed but contains mismatches.

bug.mp4

@brc-dd brc-dd added client and removed bug: pending triage Maybe a bug, waiting for confirmation labels Jul 25, 2024
@shellRaining
Copy link
Contributor Author

sorry I forget to add prevent modifier for event handle 😄, which cause this mismatches

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants