当 vue 路由器更改查询参数时防止滚动到顶部

d-_*_*_-b 7 vue.js vue-router vue-component vuejs2

当我更改路由的查询参数(和视图的props)时,如何防止页面滚动到顶部?

我试过以下没有运气:

尝试 1 - 路由的组件

当我将超时设置为任意大的数字(1 秒)时,它会在一些延迟后向下滚动。

// in my route's component
props: {...},
watch: {
  $route(to, from) {
      let y = window.scrollY;
      this.$nextTick(() => {
        setTimeout(() => {
          console.log(`scrolling to ${y}`);
          window.scrollTo(0, y);
        }, 0);
      });
    }
}
Run Code Online (Sandbox Code Playgroud)

尝试 2 - $router 的scrollBehavior

这会记录正确的y值,但不会保持旧位置。

scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition;
    }
    if (from.path !== to.path) {
      return { x: 0, y: 0 };
    }

    let existing = {
      x: window.scrollX,
      y: window.scrollY
    };
    console.log(`Existing scroll`, existing);
    return new Promise(resolve => {
      setTimeout(() => {
        resolve(existing);
      }, 0);
    });

  },

Run Code Online (Sandbox Code Playgroud)

Tit*_*ter 8

对其他答案的备注:

1 hashbag: true, .. 我在当前版本的 vue-router 文档中hashbag都找不到。hashbang可能这是一个古老的属性。

2. if (to.params.savePosition) return {} +this.$router.push({ query: query, params: { savePosition: true } })

无需使用额外的参数来savePosition解决此问题。


我的回答和评论:

const router = new VueRouter({
  mode: 'history', // or 'hash'
  routes,
  scrollBehavior (to, from, savedPosition) {
    // Exists when Browser's back/forward pressed
    if (savedPosition) {
      return savedPosition
    // For anchors
    } else if (to.hash) {
      return { selector: to.hash }
    // By changing queries we are still in the same component, so "from.path" === "to.path" (new query changes just "to.fullPath", but not "to.path").
    } else if (from.path === to.path) {
      return {}
    }

    // Scroll to top
    return { x: 0, y: 0 }
  }
})
Run Code Online (Sandbox Code Playgroud)


小智 7

我刚刚找到了一个答案。这是我的代码。默认行为将滚动到顶部,除非您传递一个 custom params,如果path提供了 a (https://router.vuejs.org/guide/essentials/navigation.html),它将被路由器忽略。

scrollBehavior (to, from, savedPosition) {
    // savedPosition is only available for popstate navigations.
    if (savedPosition) return savedPosition

    // if the returned position is falsy or an empty object,
    // will retain current scroll position.
    if (to.params.savePosition) return {}

    // scroll to anchor by returning the selector
    if (to.hash) {
      let position = {selector: to.hash}

      // specify offset of the element
      // if (to.hash === '#anchor2') {
      //   position.offset = { y: 100 }
      // }
      return position
    }

    // scroll to top by default
    return {x: 0, y: 0}
  }
Run Code Online (Sandbox Code Playgroud)

如果返回一个虚假或空对象,Vue router 将返回原始位置。然后我将把params我使用的名为“savePosition”的自定义传递给params.

this.$router.push({ query: query, params: { savePosition: true } })
Run Code Online (Sandbox Code Playgroud)

这样,您的路由器默认会滚动到顶部,除非您传递savePositionparams,或者传递散列。


小智 1

有类似的问题,仅当添加模式:历史记录和 hashbag:true 时才对我有用。这是 VueRouter 设置的外观:

mode: 'history',
hashbag: true,
scrollBehavior (to, from, savedPosition) {
    if (savedPosition) {
        return savedPosition
    } else {
        return { x: 0, y: 0 }
    }
},
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你。