一、前言
之前写了一个 happyChat 的项目,主要是想学习一下 socketIO 的使用。然后最近在给 happyChat 做前端优化和升级。发现第一版做的很 low。
需要优化的问题:
1、问题 1:滚动条会出现在头部和底部的视窗中,之前固定头部和固定底部是使用 `position:fixed`。解决方案:body 和 html 禁止 `overflow:hidden`,头部和底部是 `position:relative`,聊天视窗使用 `overflow: auto`,这样聊天视窗才会出现滚动条。滚动条不会出现在头部和底部视窗中。2、问题 2:聊天视窗一次性加载了所有的聊天内容,如果数据太多会出现超时的问题。解决方案:聊天内容查询使用分页查询,一次性查询 20 条或者 30 条。3、问题 3:群聊的时候,找不到群成员列表。解决方案:做一个群信息汇总的组件,包括群成员列表。
新增功能:(1)滚动条置底;(2)分页加载的时候,保持滚动条置于上次停留的位置。
项目【前端】源代码地址:https://github.com/saucxs/hap…
项目【后端】端源代码地址:https://github.com/saucxs/hap…
欢迎 fork 和 start。
线上地址:http://chat.chengxinsong.cn/
二、具体【视窗口】的滚动条的问题
环境:vue
我们先来看一下,给滚动条添加监听事件,必须在 created 或者 mouted 周期中,添加 scroll 的监听事件。
mounted: function () {window.addEventListener('scroll', this.handleScroll, true); // 监听(绑定)滚轮滚动事件
},
其中 handleScroll 事件是 methods 里的事件:
handleScroll() {
this.viewBox = this.$refs.viewBox;
console.log(this.viewBox.scrollTop, '到头部的距离 -------------------')
console.log(this.viewBox.scrollHeight, '滚动条的总高度 -------------------')
}
注意:div 到头部的距离 + 屏幕高度 = 可滚动的总高度 this.$refs.viewBox
取到视窗口的 dom 对象,必须确定 dom 加载完毕了。
<ul ref="viewBox">
<li v-for="item in message">
<ChatItem v-if="userInfo.user_id === item.from_user" :href="item.from_user" :img="item.avator" me="true" :msg="item.message" :name="item.name" :time="item.time"></ChatItem>
<ChatItem v-else :img="item.avator" :msg="item.message" :href="item.from_user" :name="item.name" :time="item.time"></ChatItem>
</li>
</ul>
如果我们想置底,我们必须将【滚动条总高度】赋值给【滚动条到头部的距离】。这样就置底了。
业务是这样的:(1)当进入到聊天页面时候,这时候置底。(2)如果翻看之前的聊天记录,这时候就不需要置底,保持在当前的位置。
1、先解决【进入到聊天页面时候,这时候置底】的问题
解决方案:(1)全局设置一个标志位,如果是第一次进入,【标志位为置底】,执行置底方法。(2)如果是翻看之前聊天记录,【标志位改为不置底】,不执行置底方法。(3)监听内容变化方法,判断标志位是啥,然后看是否执行置底方法。
watch: {message() {
this.viewBox = this.$refs.viewBox
if(this.type == 'bottom'){this.refresh();
}
}
},
refresh 就是一个置底方法。
refresh() {setTimeout(() => {this.viewBox.scrollTop = this.viewBox.scrollHeight}, 100)
},
2、如果翻看之前的聊天记录,这时候就【不需要置底,保持在当前的位置】
如果不置底,就是一直在保持在顶部。
思路:将加载之前的【数据高度】(此时滚动条的总高度)存放在临时变量 beforeScrollHeight 中;将数据加载之后的到【头部的距离】=【此时滚动条总高度】-【临时变量 beforeScrollHeight】。
看一下代码实现:
监听 message 值变化
watch: {message() {if(this.type == 'bottom'){this.refresh();
}else{this.nofresh()
}
}
},
主要看 nofresh 方法
nofresh() {setTimeout(() => {
this.afterScrollHeight = this.viewBox.scrollHeight - this.beforeScrollHeight;
this.viewBox.scrollTop = this.afterScrollHeight;
}, 100)
},
加载更多的方法
loadMore() {
this.beforeScrollHeight = this.viewBox.scrollHeight;
// 分页请求数据,包装数据。}
我们来看一下动态图,实现的功能
今天只把这个具体视窗口的滚动条的总结一下,其他两个问题,没有很大的意义。
【上述源码地址】项目地址:https://github.com/saucxs/hap…,欢迎 fork 和 start。