Nuxt-link 延迟转换到新页面?

Nuxt-link delay transition to new page?

这是 #1458 的跟进。我正在寻找 Nuxt 希望如何处理这个问题的方向。

我有菜单。当我点击菜单中的 nuxt-link 时,我希望在页面转换发生之前有时间关闭菜单。问题是,我只希望在您单击菜单中的 nuxt-link 时发生这种情况,而不是每次我去某个路线时发生(如上一期所述,在路线上使用中间件)。

所以有几种不同的方法可以做到这一点,我很好奇“Nuxt”方法是什么?

我们目前的做法是,禁用 nuxt-link 并捕获点击,然后执行 router.push()。

<nuxt-link :to="path" event="disabled" @click.native="delayLoad"/>

// Methods
delayLoad(event) {
     this.$store.commit("CLOSE_MENU")

     setTimeout(()=>{
        this.$router.push(event.target.pathname)
    }, 2000)
}

这是个好主意吗?我总是厌恶像这样劫持 nuxt-link 和浏览器导航。好像有点卡。

我们尝试的其他想法是在 nuxt-link 上使用查询参数,然后在中间件中使用它来延迟页面转换。这对我来说似乎更糟,因为现在我的 URL 中有一个用于动画的查询参数,这似乎是在滥用查询参数。这也会触发页面加载进度条,这并不是真正的目的,它是为了让一个顺序动画发生,然后页面加载。

在我看来,也许 nuxt-link 应该有一个延迟属性,或者页面转换配置应该允许延迟(就像它对持续时间所做的那样)?

由于 nuxt-link 本质上是 vue router-link 的包装版本,如果您查看文档,其中有一个事件 属性 接受 stringstring[],在这里查看它的源代码:https://github.com/vuejs/vue-router/blob/dev/src/components/link.js#L86 你可以看到它会在这个实例中为 disabled 注册一个监听器。传递一个空数组可能更有意义,这样就不会注册任何事件侦听器,但这是以可读性为代价的。

否则,@click.native 是处理 router-link 自定义点击处理程序的建议方法(参见:https://github.com/vuejs/vue-router/issues/800#issuecomment-254623582)。

我唯一能想到的其他问题是,如果您快速连续单击 2 个不同的 link 会发生什么,以及如果您单击多次会发生什么。可能只想添加一个变量来跟踪 link 是否已被单击以防止多次触发 setTimeout,这可以将您从页面 A 导航到 B,然后再到C 因为所有 timeouts 如果不取消则触发。或者您可能只想导航到单击的 'last' link,因此如果单击另一个 link,您将取消之前的 setTimeout。这实际上是一个边缘案例,可能不会成为问题,但值得探索。

否则,IMO,我觉得不错。这似乎是无需创建自定义组件/插件即可实现的最简单方法。我不是专家,但很可能我也将如何实现此功能。很高兴看到延迟选项,因为我可以看到自己也使用该功能以及 vuetify。

另一种可能的方法是在 beforeTransition 中开店 commithttps://nuxtjs.org/api/configuration-transition/ 虽然我不确定是否可以访问那里的商店,因此您可能还必须为此编写一个自定义插件。同样,对于一个简单的延迟动画来说,它似乎比它的价值更复杂。简单、有效的代码有时是最好的解决方案,即使它不是最可扩展的选择。

另请参阅: 另一种处理方式。

我也想这样做,并提出了以下解决方案。使用新的 slots api 您可以更优雅地自定义 nuxt-link 行为:

<nuxt-link v-slot="{ route, href }" :to="path" custom>
  <a :href="href" @click.prevent="$emit('navigate', route)">
    <slot></slot>
  </a>
</nuxt-link>

这将使 link 发出一个以路线作为参数的导航事件。然后在包含菜单组件的任何地方监听此事件,如下所示:

<template>
  <transition
    name="fade"
    @after-leave="maybeNavigate"
  >
    <MainMenu
      v-if="menuIsVisible"
      @navigate="navigate"
    />
  </transition>
</template>

<script>
export default {
  data: () => ({
    menuIsVisible: false,
    navigateToOnMainMenuClose: null,
  }),
  methods: {
    navigate(route) {
      this.navigateToOnMainMenuClose = route
      this.menuIsVisible = false
    },
    maybeNavigate() {
      if (this.navigateToOnMainMenuClose) {
        this.$router.push(this.navigateToOnMainMenuClose)
        this.navigateToOnMainMenuClose = null
      }
    },
  },
}
</script>

每当您单击菜单中的导航 link 时,将存储路线并关闭菜单。菜单退出动画完成后,maybeNavigate() 将推送存储的路由,如果有的话。这消除了对 setTimeout 的需要,如果您设法快速连续单击多个 link,则只会存储最后一个并导航到。