解决Vue页面固定滚动位置的处理办法

前端之家收集整理的这篇文章主要介绍了解决Vue页面固定滚动位置的处理办法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

最近做项目遇到一个问题,就是Vue滚动不固定,网上找了一些资料,说下 vue 固定滚动位置的处理办法.

问题描述:

通常见于 列表页List -> 详情页Detail 的情况,从列表的某一项x 进入到详情页,再返回的时候,希望列表的位置固定在x,而不是回到顶部了.

vue-router 里面是有一个 scrollBehavior 的,但是这个玩意只能在 history 模式下面使用,而我用的 hash 模式.

所以我们要自己实现嘛,思路简单:List 里面监听滚动,记录滚动位置 pos,从 Detail 返回到 List 里面的时候,读取 pos.

遇见了一个问题:

每次返回 List,都是直接滚动到顶部,每次都是,每次都是! 把 pos 打印出来,发现是 0,而不是我们所存的值. 日了,明明切换之前还是的,回来就不是了.

然后发现了路由每次切换都会触发 onscroll 事件,日了狗,为毛.我都没有滚动页面,为什么会触发 onscroll 事件。

刚开始怀疑 hash 变化会导致 onscroll 事件的触发,所以我就在浏览器里面手动输入了几个不存在的路由:

没有发现 scroll 被触发,所以这个嫌疑排出.

然后怀疑 vue-router 里面是不是绑定了 scroll 事件,没发现然后又想,没绑定 scroll 事件,那么修改 scrollTop 值会不会也触发 scroll 事件.

好吧还发现新知识点了:

scrollTop 值的改变,的确会触发 scroll 事件.

那么我就想,是不是 vue-router 里面存在修改 scrollTop 值的行为,也没有发现.

然后我又想,数据是动态渲染的,所以是不是和元素的增删改查相关。

元素增加-> 页面高度变了 -> 页面高度变化,也触发 scroll 事件?

所以我用 vue-cli 新建了项目,放了两个没有增删改查的路由

然后日了狗的,我看见从 foo -> bar -> foo,的时候,foo的滚动条位置还在之前我滚动到的地方.

突然想起来浏览器是可以自己记录滚动条位置的.

是不是浏览器干的?

从详情页返回到列表页面,列表会重新渲染,时序大概是这样: 返回列表页 1 渲染页面 2

而浏览器恢复滚动条的位置的操作,是在 1 和 2 之间,这个时候就出问题了:如果你页面上面的数据都是渲染出来的,浏览器就会发现:

页面的高度<=屏幕的高度,不存在滚动条,此时 document.body.scrollTop = 0; 所以会设置 document.body.scrollTop = 0 修改了 document.body.scrollTop 触发了 scroll 事件,scroll 里面又重写了 pos

等你数据渲染结束之后,读到的就是 0了.

如果发现你页面高度大于屏幕高度,但是页面高度是 n,而 pos 的值是: n + x,比当前页面的最大的 scrollTop 值还大,这个时候,document.body.scrollTop 的值就会等于 n. 当你的数据渲染结束,开始定位,日了,没定准.

所以我们要解决这个问题.

当然是想到了 keep-alive,刚启用的时候,发现的确不错. 但是同时也发现:

列表项目靠前的,往返操作的定位都很准,越往后越不行,直接拉到底,再返回发现定位到的一般都是第二个第三个列表项目.

所以这个就很有意思了,我大概猜测了一下浏览器的滚动位置恢复行为:

当 hashchange 的时候。拿到当前页面的 document.body.scrollTop 值,和自己存储的滚动条位置。二者取最小的值,设置成当前的 document.body.scrollTop 的值,当使用 keep-alive 的时候,因为 hashchange 事件处理和页面渲染是并行的,所以有时hashchange 拿到的 document 的高度是已经渲染过几个元素的高度,这个就是为什么定不准的原因.

好吧,现在的情况是:

keep-alive 定不准,不可靠,所以需要我们自己来重新定位.

ok,1 先绑定 scroll 事件:

2 再屏蔽掉浏览器自动恢复滚动位置行为带来的影响

a 在 hashchange 时强制 document.body.scrollTop = 0

b 在 scroll 事件里面,当 document.body.scrollTop = 0 的时候不做 存操作.

3 在读操作里面,设置一个定时任务,去判断 document.body.scrollTop 的值和你保存的位置是不是相同的

到这里实际上已经大体实现了,返回恢复滚动条位置的功能,而上面的代码需要更多的优化,

具体代码见:nofollow" target="_blank" href="https://github.com/helicopters/wc-scroll-position">项目地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

猜你在找的Vue相关文章