Vue记住滚动条和实现下拉加载的完美方法
作者:hezf
滚动条
常见于移动端 App 在滚动点击进入的时候
问题描述
当我们在开发 web app 的时候,经常会遇到一个问题,就是当从一个可滚动的列表页进入到下一个详情页面,然后返回列表页面的时候,很难去还原滚动条的状态,无法记住进来时候的位置。
以前我尝试过很多方法:
- 有 vue-router 自带的 scrollBehavior,需要记住 scrollTop,然后还原,但是管理这个 scrollTop 显得很麻烦,有的时候还不容易取值还有使用纯 CSS 的方式,在列表页面放置一个 router-view,详情页面利用 position 和 z-index 覆盖列表页面,返回后直接显示的就是原来的列表页面,这个必须把各层页面路由预先配置好,不然就会显示混乱了,并且同一个页面出现在不同的子路由下,需要配置多次,比如商品详情需要配置在很多个地方,造成冗余
- 以上解决方案都不理想
解决方案
后来我参考 keep-alive 开发了 vue-page-stack 来保存 Vue 页面的栈,即 Vue 中的虚拟 dom,但是滚动条的问题仍然没解决。因为虚拟 dom 没有记录各个组件的滚动状态,所以无法恢复。
在我使用 cube-ui 的时候发现,使用这个组件库里面的滚动容器,是可以还原出滚动条的,进一步发现是黄轶老师的 better-scroll 的原因。
通过查看 bs 的源码发现,原来是 bs 的内部实现不是原生滚动,而是记录一些滚动的信息,其中最重要的就是 x 和 y,也就是滚动的值,自己实现了一套滚动行为通过 transform 去实现,在还原虚拟 dom 的时候,滚动的信息也被还原了。
最终就是 vue-page-stack + bs 可以完美实现页面栈的还原
下拉加载
这个问题多见于消息记录等查询,在小程序中也会这遇到这样的问题
问题描述
绝大多数滚动场景都是上拉加载,上拉加载的时候,加载的内容在滚动区域的下方出现,加载之后,我们将数据添加到列表,由 Vue 等负责渲染新加载的内容,我们继续上拉就可以继续滚动查看。
但在我们的场景下,在某一会话中翻阅消息记录的时候,是下拉加载更多消息,加载后,继续下拉慢慢滚动查看。这就导致了一个很严重的问题:下拉加载后出现的内容在滚动区域的上方,不做任何处理的话加载后会直接跳到新加载内容的最上方,因为滚动距离没变,这就出问题了,和我们想实现的不一致。
解决方案
也想了很多的方法,包括计算新增加消息的总长度,然后滚回来,但是消息的类型和高度不一致,计算会有误差。
最终想到的处理办法就是:
- 通过接口获取到加载信息后首先标记(使用 shouldScroll 标记)后端返回的第一条信息,也就是加载后我们的视角要看到的新内容
- messageList 更新后,Vue 会更新数据和视图,这时候页面 dom 被更新了
- MessageItem 组件 mounted 后,这时候已经完成了视图的渲染,通过检查标记(shouldScroll),通知父容器滚动到刚才标记的位置,也就是加载的第一条信息处,这样也就把渲染和滚动做到一起了
以上两个问题在下图均有体现,效果还可以,如下:
以上内容在我的即时通讯应用客户端中均有体现,欢迎查看源码
总结
到此这篇关于Vue记住滚动条和实现下拉加载的完美方法的文章就介绍到这了,更多相关Vue滚动条和下拉加载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!