滚动行为 缓存之前的位置

开发中的问题:
场景1 在用前端路由,当切换到新路由时,想要页面滚动到顶部,或者保持原先滚动位置,就像重新加载页面那样。
场景2 在一个很长的列表页往下拉,然后点击列表中的某一数据进入到详情页查看。此时决定返回列表也继续查看列表。很多情况下,由于列表页的组件已经被销毁,所以我们返回到列表页面会置顶,不得不重新下拉查看列表,这样就做了很多没有必要的操作,也是不符合用户的预期。

滚动行为
通过vue-router自定义路由切换时页面如何滚动。当跳转新路由时,页面滚动到某个位置;切换路由时页面回到之前的位置。

// srcollBehavior 方法
const router = createRouter({
  history: createWebHashHistory(), // createWebHistory 是 Vue Router 提供的一种基于浏览器 history API 的路由模式
  routes:[...],
  srcollBehavior(to, from, savedPositon){
    // return 期望滚动到哪个的位置
  }
})

srcollBehavior 方法接收 to 和 from路由对象,第三个参数savedPositon 当且仅当 popstate导航(通过浏览器前进/后退按钮触发)时才可用。
return{ x:number, y:number} // 来控制页面滚动的位置
对于所有路由导航,简单地让页面滚动到顶部。

srcollBehavior (to, from, savedPositon ){
   return {x:0,y:0}
}
// 或
const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    // 始终滚动到顶部
    return { top: 0 }
  },
})

新增异步滚动:
当页面数据需要请求加载延迟的情况下,页面如果直接滚动,会出现滚动后,页面数据请求回来,DOM重新渲染,滚动失效。

scrollBehavior(to, from, savedPosition){
  return new Promise((resolve,reject)=>{
     setTimeour(()=>{
        resolve({x:0,y:0})
     },500)
  })
}

滚动到元素位置
可以通过 el 传递一个 CSS 选择器或一个 DOM 元素。在这种情况下,top 和 left 将被视为该元素的相对偏移量。

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    // 始终在元素 #main 上方滚动 10px
    return {
      // el: document.getElementById('main'),
      el: '#main',
      top: -10,
    }
  },
})

滚动到锚点位置

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    if (to.hash) {
      return {
        el: to.hash,
      }
    }
  },
})

滚动到之前的位置
在按下浏览器 后退/前进 按钮,或者调用 router.go() 方法时,页面会回到之前的滚动位置:

const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition
    } else {
      return { top: 0, behavior: 'smooth' }
    }
  },
})
// 如果返回一个false的值,或者是一个空对象,则不会发生滚动。我们还可以在返回的对象添加behavior:‘smooth’,让滚动更加丝滑。

scrollIntoView()
如果想要在特定的按钮点击事件中实现平滑滚动可以使用 scrollIntoView 方法。scrollIntoView()将调用它的元素滚动给到浏览器窗口的可见区域顶部。

element.scrollIntoView(); // 等同于 element.scrollIntoView(true)
element.scrollIntoView(alignToTop); //布尔参数。接受布尔值主要还是为了兼容不支持平滑滚动(老版)的浏览器
element.scrollIntoView(scrollIntoViewOptions); //对象参数
参数:
alignToTop:true时,相当于{behavior: ‘auto’, block: ‘start’, inline: ‘nearest’}; false时,相当于{behavior: ‘auto’, block: ‘end’, inline: ‘nearest’}; 未传入参数时,默认值为:{behavior: ‘auto’, block: ‘start’, inline: ‘nearest’}
scrollIntoViewOptions:一个包含下列属性的对象。

使用缓存,即不销毁列表页

// APP.js中
<template>
  <div id="app">
    <!-- <router-view/> -->
    <keep-alive>
        <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive" />
  </div>
</template>
// router.js中
 routes: [
    {
      path: '/',
      name: 'List',
      //component: List
      component: () => import('./views/index/list.vue'),
      meta: {
        keepAlive: true // 需要缓存
      }
    },
    {
      path: '/content/:contentId',
      name: 'content',
      component: () => import('./views/index/content.vue'),
      meta: {
        keepAlive: false // 不需要缓存
      }
    },
]

使用路由守卫
原理就是在beforeRouterLeave的路由钩子记录当前页面滚动位置。

//在页面离开时记录滚动位置,这里的this.scrollTop可以保存在vuex的state或者浏览器本地
beforeRouteLeave (to, from, next) {
    this.scrollTop = document.documentElement.scrollTop || document.body.scrollTop
    next()
  },

//进入该页面时,用之前保存的滚动位置赋值
beforeRouteEnter (to, from, next) {
    next(vm => {
      document.body.scrollTop = vm.scrollTop
    })
  },
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简 。单

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值