最近做项目遇到一个问题,就是Vue滚动不固定,网上找了一些资料,说下 vue 固定滚动位置的处理办法.
问题描述:
通常见于 列表页List -> 详情页Detail 的情况, 从列表的某一项x 进入到详情页, 再返回的时候, 希望列表的位置固定在x, 而不是回到顶部了.
vue-router 里面是有一个 scrollBehavior 的, 但是这个玩意只能在 history 模式下面使用, 而我用的 hash 模式.
所以我们要自己实现嘛, 思路简单:List 里面监听滚动, 记录滚动位置 pos, 从 Detail 返回到 List 里面的时候, 读取 pos.
mounted () { // 读 setTimeut(function(){ document.body.scrollTop = parseInt(sessionStorage.getItem('pos')); }, 1000); // 存 window.onscroll = function () { sessionStorage.setItem('pos', document.body.scrollTop); } }
遇见了一个问题:
每次返回 List, 都是直接滚动到顶部, 每次都是, 每次都是! 把 pos 打印出来, 发现是 0, 而不是我们所存的值. 日了, 明明切换之前还是的, 回来就不是了.
然后发现了路由每次切换都会触发 onscroll 事件, 日了狗, 为毛.我都没有滚动页面, 为什么会触发 onscroll 事件。
刚开始怀疑 hash 变化会导致 onscroll 事件的触发, 所以我就在浏览器里面手动输入了几个不存在的路由:
/foo/bar
没有发现 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
新闻热点
疑难解答
图片精选