滚动行为

使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。

注意: 这个功能只在支持 history.pushState 的浏览器中可用。

当创建一个 Router 实例,你可以提供一个 scrollBehavior 方法:

  1. const router = createRouter({
  2. history: createWebHashHistory(),
  3. routes: [...],
  4. scrollBehavior (to, from, savedPosition) {
  5. // return 期望滚动到哪个的位置
  6. }
  7. })

scrollBehavior 函数接收 tofrom 路由对象,如 Navigation Guards。第三个参数 savedPosition,只有当这是一个 popstate 导航时才可用(由浏览器的后退/前进按钮触发)。

该函数可以返回一个 ScrollToOptions 位置对象:

  1. const router = createRouter({
  2. scrollBehavior(to, from, savedPosition) {
  3. // 始终滚动到顶部
  4. return { top: 0 }
  5. },
  6. })

你也可以通过 el 传递一个 CSS 选择器或一个 DOM 元素。在这种情况下,topleft 将被视为该元素的相对偏移量。

  1. const router = createRouter({
  2. scrollBehavior(to, from, savedPosition) {
  3. // 始终在元素 #main 上方滚动 10px
  4. return {
  5. // 也可以这么写
  6. // el: document.getElementById('main'),
  7. el: '#main',
  8. top: -10,
  9. }
  10. },
  11. })

如果返回一个 falsy 的值,或者是一个空对象,那么不会发生滚动。

返回 savedPosition,在按下 后退/前进 按钮时,就会像浏览器的原生表现那样:

  1. const router = createRouter({
  2. scrollBehavior(to, from, savedPosition) {
  3. if (savedPosition) {
  4. return savedPosition
  5. } else {
  6. return { top: 0 }
  7. }
  8. },
  9. })

如果你要模拟 “滚动到锚点” 的行为:

  1. const router = createRouter({
  2. scrollBehavior(to, from, savedPosition) {
  3. if (to.hash) {
  4. return {
  5. el: to.hash,
  6. }
  7. }
  8. },
  9. })

如果你的浏览器支持滚动行为,你可以让它变得更流畅:

  1. const router = createRouter({
  2. scrollBehavior(to, from, savedPosition) {
  3. if (to.hash) {
  4. return {
  5. el: to.hash
  6. behavior: 'smooth',
  7. }
  8. }
  9. }
  10. })

延迟滚动

有时候,我们需要在页面中滚动之前稍作等待。例如,当处理过渡时,我们希望等待过渡结束后再滚动。要做到这一点,你可以返回一个 Promise,它可以返回所需的位置描述符。下面是一个例子,我们在滚动前等待 500ms:

  1. const router = createRouter({
  2. scrollBehavior(to, from, savedPosition) {
  3. return new Promise((resolve, reject) => {
  4. setTimeout(() => {
  5. resolve({ left: 0, top: 0 })
  6. }, 500)
  7. })
  8. },
  9. })

我们可以将其与页面级过渡组件的事件挂钩,以使滚动行为与你的页面过渡很好地结合起来,但由于使用场景可能存在的差异和复杂性,我们只是提供了这个基础来实现特定的用户场景。