1. 开始
有个项目需要用到IM聊天功能,在向上翻更多聊天记录时,需要将位置固定,也就是加载更多时不要滚动到顶部,也不要跳动、抖动。
尝试了n种方法,终于可以了,这里记录下。
2. 尝试方案
2.1. overflow-anchor
尝试用css
自带属性overflow-anchor: auto
解决这一问题,但是它的兼容性太差了,在chrome
、开发者工具中调试的效果可以,但是真机小程序、H5都不行。
此外,这一属性需要scrollTop
不能为0
,也就是在插入数据之前检查下scrollTop
,如果为0
,则调用API让scroll-view
向下滚动一点。
2.2. 赋值前将scrollY
设置为false
这种方式是想在list
添加前将scroll-view
固定,然后在前面插入数据,想法是挺好的,但是一插入数据,scroll-view
还是滚动到了顶部,也就是scroll-view
内部是让scroll-top
在插入数据前后不变。
2.3. 赋值后立即设置scrollTop
这种方式是想在数据插入后立即滚动到原来的位置,H5是没问题的,小程序不可以,因为小程序设置scrollTop
是异步的,list
一旦赋值,并传递到渲染层就渲染了,这时候再改变scrollTop
,或设置scrollInfoView
会导致页面抖动。
2.4. 赋值后立即调用scrollInfoView
无效的原因与上相同。
3. 解决方法
3.1. scroll-view
倒置
采用的是scroll-view
倒置,列表数据也倒置,这样每次加载下一页,可以当成是普通list
的loadMore
,从而解决跳动的问题。
scss
.press-message-detail {
transform: rotate(180deg);
.press-message-item {
transform: rotate(180deg);
}
}
调用者无需关心list
的翻转,由组件内部处理:
ts
export default {
computed: {
reversedList() {
const res = [
...this.list,
];
res.reverse();
return res;
},
},
}
3.2. 隐藏scrollbar
同时要注意隐藏scrollbar
,因为scrollbar
此时跑到了左边。用下面的方式在小程序中无效,采用的是Dom覆盖的方式。
scss
::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
color: transparent;
}
3.3. 数据少的情况
此外,当聊天内容不足一屏时,消息是堆在下面的,因为scroll-view
被倒置了。
解决方案是,设置一个placeholder
的dom
,设置为flex:1
,让它和消息内容共享父容器的高度。
4. 体验地址
目前在press-ui示例项目中可以查看效果,三端(H5、微信小程序、QQ小程序)表现一致。
另外,欢迎使用press-ui
跨端组件库。
5. 资料
网上被这一问题困扰的人还挺多的,这是我查阅资料时看到的一部分: