聊天框 - 微信加载历史数据的效果原来这样实现的
点击关注公众号,“技术干货”及时达!前言我记得2021年的时候做过聊天功能,那时业务也只限微信小程序
那时候的心路历程是:
?卧槽,让我写一个聊天功能这么高大上??
嗯?这么简单,不就画画页面来个轮询吗,加个websocket也还行吧
然后,卧槽?这查看历史聊天记录什么鬼,页面闪一下不太好啊,真的能做到微信的那种效果吗
?然后一堆调研加测试,总算在小程序中查看历史记录没那么鬼畜了,但是总是感觉不是最佳解决方案。
?那时打出的子弹,一直等到现在击中了我
?最近又回想到了这个痛点,于是网上想看看有没有大佬发解决方案,结果还真被我找到了。
image.png正文开始1,效果展示上才艺~~~
222.gif2,聊天页面2.1,查看历史聊天记录的坑常规写法加载历史记录拼接到聊天主体的顶部后,滚动条会回到顶部、不在原聊天页面
直接上图
111.gif而我们以往的解决方案也只是各种利用缓存、scroll的滚动定位把回到顶部的滚动条重新拉回加载历史记录前的位置,好让我们可以继续在原聊天页面。
但即使我们做了很多优化,也会有安卓和苹果部分机型适配问题,还是不自然,可能会出现页面闪动。
其实吧,解决方案只有两行css代码~~~
2.2,解决方案:flex神功想优雅顺滑的在聊天框里查看历史记录,这两行css代码就是flex的这个翻转属性
dispaly:flex;
flex-direction:column-reverse
「灵感来源~~~」
333.gif小伙伴可以看到,在加载更多数据时
?滚动条位置没变、加载数据后还是原聊天页面的位置
?这不就是我们之前的痛点吗~~~
所以,我们只需要翻转位置,用这个就可以优雅流畅的实现微信的加载历史记录啦
flex-direction: column-reverse
官方的意思:指定Flex容器中子元素的排列方向为列(从上到下),并且将其顺序反转(从底部到顶部)
如果感觉还是抽象,不好理解的话,那就直接上图,不加column-reverse的样子
image.png加了column-reverse的样子
image.png至此,我们用column-reverse再搭配data数据的位置处理就完美解决加载历史记录的历史性问题啦
代码放最后啦~~~
2.3,其他问题2.3.1,数据过少时第一屏展示因为用了翻转,数据少的时候会出现上图的问题
只需要.mainArea加上height:100%
然后额外写个适配盒子就行
flex-grow:1;
flex-shrink:1;
image.png2.3.2,用了scroll-view导致的问题这一part是因为我用了uniapp里 scroll-view组件导致的坑以及解决方案,小伙伴们没用这个组件的「可忽略~~~」
如下图,.mainArea使用了height:100%后,继承了父级高度后scroll-view滚动条消失了。
image.png.mainArea去掉height:100%后scroll-view滚动条出现,但是第一屏数据过多时不会滚动到底部展示最新信息
image.png解决方案:第一屏手动进行滚动条置顶
scrollBottom(){
if(this.firstLoad)return;
//第一屏后不触发
this.$nextTick(()={
constquery=uni.createSelectorQuery().in(this);
query
.select("#mainArea")
.boundingClientRect((data)={
console.log(data);
if(data.height+this.chatHeight){
this.scrollTop=data.height;//填写个较大的数
this.firstLoad=true;
}
})
.exec();
},
3,服务端使用koa自己搭一个websocket服务端
3.1 服务端项目目录image.pngpackage.json
{
"name":"websocketapi",
"version":"1.0.0",
"description":"",
"main":"index.js",
"scripts":{
"test":"echo\"Error:notestspecified\"exit1"
},
"author":"",
"license":"ISC",
"dependencies":{
"koa":"^2.14.2",
"koa-router":"^12.0.1",
"koa-websocket":"^7.0.0"
}
}
koa-tcp.js
constkoa=require('koa')
constRouter=require('koa-router')
constws=require('koa-websocket')
constapp=ws(newkoa())
constrouter=newRouter()
/**
*服务端给客户端的聊天信息格式
*{
id:lastid,
showTime:是否展示时间,
time:nowDate,
type:type,
userinfo:{
uid:this.myuid,
username:this.username,
face:this.avatar,
},
content:{
url:'',
text:'',
w:'',
h:''
},
}
消息数据队列的队头为最新消息,以次往下为老消息
客户端展示需要reverse():客户端聊天窗口最下面需要为最新消息,所以队列尾部为最新消息,以此往上为老消息
*/
router.all('/websocket/:id',async(ctx)={
//constquery=ctx.query
console.log(JSON.stringify(ctx.params))
ctx.websocket.send('我是小服,告诉你连接成功啦')
ctx.websocket.on('message',(res)={
console.log(`服务端收到消息,${res}`)
letdata=JSON.parse(res)
if(data.type==='chat'){
ctx.websocket.send(`我也会说${data.text}`)
}
})
ctx.websocket.on('close',()={
console.log('服务端关闭')
})
})
//将路由中间件添加到Koa应用中
app.ws.use(router.routes()).use(router.allowedMethods())
app.listen(9001,()={
console.log('socketisconnect')
})
切到server目录下yarn
然后执行nodemon koa-tcp.js
没有nodemon的小伙伴要装一下
image.png「代码区」
完整项目Github传送门
聊天页面的核心代码如下(包含data数据的位置处理和与服务端联动)
https://code.juejin.cn/pen/7337211042621521959(跳转链接或者点击下方阅读原文查看)
完结这篇文章我尽力把我的笔记和想法放到这了,希望对小伙伴有帮助。
到这里,想给小伙伴分享两句话
?现在搞不清楚的事,不妨可以先慢下来,不要让自己钻到牛角尖了
一些你现在觉得解决不了的事,可能需要换个角度
?欢迎转载,但请注明来源。
最后,希望小伙伴们给我个免费的点赞,祝大家心想事成,平安喜乐。
image.png点击关注公众号,“技术干货”及时达!
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线