vue-router URL里存在锚点导致不能再次跳转的可能解决办法

有时候我们会碰到这么一个场景:我们可能希望点击页面上的某个按钮,然后就会滚动到页面的某一块上,也就是所谓的“滚动到锚点”的功能。这个其实很好实现,vue-router的官方文档里已经给出了写法:

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    if (to.hash) {
      return {
        selector: to.hash
      }
    }
  }
});

但是这么写存在一个问题。比如我在页面顶部有一个链接,点击之后就会跳转到底部(demo在这里):

<router-link to="#bottom">jump to bottom</router-link>
<!--...-->
<h1 id="bottom">This is bottom!</h1>

这应该是很常见的实现方式了。

但是这么实现有个问题,如果我先点击了这个链接跳转到了底部(此时URL为/#bottom),然后我再手动从底部把页面滚动到顶部,此时再次点击链接,就不会跳转了。为什么?因为URL已经是/#bottom了,当然不会再次跳转。

所以,我们就会有这么一个想法:能不能让目标组件离开可视范围之后就自动修改URL呢?这样我们就能反复跳转了。比如,当这个bottom不可见的时候,我们就自动把URL修改成/,这样我们再次点击链接的时候,就能再次跳转。但是,摆在我们面前的是这样几个问题:

  • 如何修改URL而不造成页面刷新、滚动?
  • 如何尽可能让URL美观?
  • 如何判断组件是否可见?

让URL改变而不刷新页面的API早就有了,就是H5的history API,而且兼容性也已经很好了。因为vue-router的history模式是基于history API的,所以,我们最直接的想法就是这么写:

this.$router.replace('/')

但是这样会报重复路由Avoided redundant navigation to current location: "/"的错,而且可能会导致页面回到顶部,并不是我们想要的方案。

那么,直接用history API呢?比如,我们也许可以这么写:

history.replaceState(
  null,
  document.title,
  location.pathname + location.search
);

但是这样并不会起到作用,因为vue-router内部的hash值并没有变化,我们只是修改了URL而已,仍然无法完成跳转。

我们可能还会想到直接修改URL的hash部分:

location.hash = '';

但是这样第一个是不美观(会让URL变成/#),第二个是在相当多的浏览器上会直接跳转到页面顶部,因为/#代表的就是页面的顶部。

我们可能还会想到直接修改location.href,但这就会触发页面刷新,显然是不行的。

所以,综合一下,其实我们可以采用这样的办法:

location.hash = '_';
history.replaceState(
  null,
  document.title,
  location.pathname + location.search
);

不用$router的理由已经说过了,不再赘述。这一段是什么意思呢,第一个是先清除现有的锚点,设置到另一个不存在的锚点上,这样就不会触发页面滚动,同时也能确保正常跳转;然后再使用history API去修改URL,达到美观的目的。

完成了核心逻辑之后,下面就是如何判断组件的可见性。传统的方法想必大家都会,监听scroll事件,然后判断目标组件和顶部的距离;不过在现代浏览器里,有个新的API IntersectionObserver,就是为了解决可见性的问题。具体的写法这篇文章里有提到,我就不再多说了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: scrollBehavior是vue-router中的一个方法,用于设置在路由切换时页面滚动行为。它接收三个参数,to表示即将跳转到的路由对象,from表示当前所在的路由对象,savedPosition会在使用前进或后退按钮切换路由时被记录下来,如果该参数存在,则表示用户使用了浏览器的前进或后退功能,可以使用该参数将页面恢复到之前滚动的位置。如果返回false或空对象,则不会发生任何滚动行为。 ### 回答2: vue-router中的scrollBehavior是用来控制页面切换时滚动行为的。它可以被用来定制页面切换时的滚动位置。 scrollBehavior是一个被注册在全局路由对象或每个路由配置中的函数。它接收三个参数:to(即将进入的目标路由对象),from(当前导航正要离开的路由对象)和savedPosition(之前导航时保存的滚动位置)。 scrollBehavior函数需要返回一个包含滚动位置的坐标对象,或一个选择器字符串,或者是一个锚点指令。如果返回导航对象,会回到default行为。 我们可以利用scrollBehavior来定制滚动位置。比如,如果我们想让页面每次切换都回到顶部,我们可以在scrollBehavior中返回{x: 0, y: 0}来指定滚动位置为顶部。 另外,我们还可以根据不同的路由配置定制不同的滚动位置。我们可以通过检查to和from的路由对象来决定返回的滚动位置。例如,如果我们想在某个特定的路由中,每次切换都滚动至底部,我们可以在scrollBehavior中检查to的路由对象,如果是特定的路由,返回{x: 0, y: document.documentElement.scrollHeight}。 总的来说,scrollBehavior可以让我们自定义页面切换时的滚动行为,根据需求来控制滚动位置,使用户体验更加友好。 ### 回答3: scrollBehavior是Vue Router中的一个配置选项,用于控制路由切换时页面滚动的行为。它可以通过设置一个函数来定制滚动行为,该函数会在路由切换时被调用。 这个函数接收三个参数:to(要进入的目标路由对象)、from(当前导航正要离开的路由对象)和savedPosition(点击历史记录返回时的位置信息)。我们可以利用这些参数来决定页面如何滚动。 函数需要返回一个包含滚动位置信息的对象,可以有以下属性: 1. x:横向滚动位置,默认为0; 2. y:纵向滚动位置,默认为0; 3. behavior:滚动行为,默认为auto,可选值有auto、smooth。 举个例子来说,如果我们希望路由切换后页面滚动到顶部,可以在scrollBehavior函数中返回{ x: 0, y: 0 }。如果我们希望切换后页面滚动到之前保存的位置,可以通过读取savedPosition参数来实现。 另外,我们也可以根据路由对象的不同属性来设置不同的滚动行为。比如,我们可以根据目标路由和源路由的路径来实现更精确的滚动行为。 总之,scrollBehavior功能强大,可以根据具体需求来定制页面滚动的行为,使页面切换更加平滑和符合用户预期。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值