1、项目引言
2、腾讯云后台配置TXIM
3、配置项目并实现IM登录
4、会话好友列表的实现
5、聊天输入框的实现
6、聊天界面容器的实现
7、聊天消息项的实现
8、聊天输入框扩展面板的实现
9、聊天会话管理的实现
10、聊天记录的加载与消息收发
11、定位SD配置与收发定位消息
12、贴图表情的定制化开发
13、腾讯云后台配置TRTC功能
14、集成音视频通话功能
15、集成仿微信的拍照,相册选择插件
16、集成美颜功能
17、集成TPNS消息推送(暂未接入)
@
目录上一次我们讨论过聊天输入框的实现,实现文本,语音,标签的编辑发送,而本次我们的关注点将回归到整个聊天界面容器的实现。
一般情况下,开发者会采用直接在对应的界面中实现聊天界面UI的方式做开发。这种开发思路无可厚非,但是如果我们要实现跨平台的聊天IM,那么我们不免要遇到组件之间的事件冲突,多平台表现差距的问题,特别是在聊天中我们还需要实现滚动加载。如果说我们在每个界面都实现了一套代码,那么会导致整体代码的可维护性下降,因此我们有必要实现一个聊天界面容器,将消息显示,滚动加载,长按菜单,输入,编辑等都在这里面做好兼容处理,使得界面和业务组件实现解耦合。
聊天界面容器的设计很简单,我们大概整理一下需要实现以下几点功能。
首先我们需要明确我们的聊天界面肯定是需要滚动的,并且在接收/发送消息的时候我们需要滚动在最底部,类似微信收发消息的效果,组件我们肯定只有scrollView可以使用,具体实现如下
<scroll-view ref="scroll" class="chat-layout__scroll" :style="{ height: scrollBoxHeight }" :scroll-y="!inUpperLoading" :upper-threshold="0" :show-scrollbar="false" :scroll-top="scrollTop" @scrolltoupper="onScrollToUpper" @click="onScrollClick" @scroll="onScroll" > <text v-if="inUpperLoading && !end" class="chat-layout__scroll-loading" > </text> <slot></slot> <view ref="ending"></view> </scroll-view>
实现滚动到底部,一般而言是只能使用scrollTop,而这样为了兼容nvue,我们采用weex原生的dom模块获取可滚动高度 - 容器高度就可以实现可滚动高度。
async scrollToBottom (retouchCount) { if (this.inUpperLoading || this.scrollBottoming) { return } this.scrollBottoming = true // await this.$nextTick() // this.$utils.delay(100) // let view = await this.$utils.query(this, '.chat-layout__scroll') // this.scrollTop = view.scrollHeight // nvue必须使用下面这种 await this.$nextTick() dom.scrollToElement(this.$refs.ending, { animated: false }) this.scrollBottoming = false await this.$nextTick() retouchCount = retouchCount || 0 retouchCount++ // 最多5次重新滚动到底部的测试, nvue下面的渲染并且是nextTick之后就百分百正常 dom.getComponentRect(this.$refs.scroll, ({ size }) => { let { detail } = this.scrollEvent if (!detail) { this.scrollTop = 0 if (retouchCount < 5) { this.scrollToBottom(retouchCount) } } else { this.scrollTop = detail.scrollHeight - size.height // console.log('重新定位scrollTop') if (retouchCount < 5) { this.scrollToBottom(retouchCount) } } }) }
一般情况下在vue界面,我们input focus之后是会自动适应输入法高度,然而在nvue中,当我们界面中嵌套了视频播放器之类的,会导致input高度计算错误,因此我们需要手动监听输入法高度变化,然后做一个适应性的收缩界面容器即可。
<view class="chat-layout" :style="{ paddingBottom: paddingBottomHeight }" > </view>
uni.onKeyboardHeightChange(this.onKeyboardHeightChange) // methods中 async onKeyboardHeightChange ({ height }) { this.paddingBottomHeight = height await this.$nextTick() height && this.scrollToBottom() },
滚动加载有很多方式实现,这里我们只简易的实现了一个,监听scrollView的scrolltoupper事件确定是否加载,然后我们抛出给业务层控制滚动加载。
<scroll-view ref="scroll" class="chat-layout__scroll" :style="{ height: scrollBoxHeight }" :scroll-y="!inUpperLoading" :upper-threshold="0" :show-scrollbar="false" :scroll-top="scrollTop" @scrolltoupper="onScrollToUpper" @click="onScrollClick" @scroll="onScroll" >
onScrollToUpper: throttle(async function() { if (this.inUpperLoading || this.disableUpperLoading || this.end) { return } this.inUpperLoading = true let oldChildrens = this.$refs.scroll.children.length this.$emit('upperLoading', async isEnd => { if (isEnd) { this.disableUpperLoading = true } await this.$nextTick() let newChildrens = this.$refs.scroll.children.length this.inUpperLoading = false let refEl = this.$refs.scroll.children[newChildrens - oldChildrens] dom.scrollToElement(refEl, { animated: false }) }) }, 200, { leading: true, trailing: false }),
而对于业务层来说,接收到upperLoading事件之后做数据加载,然后反馈加载完成即可
async loadMoreLog (next) { console.log('loadMoreLog') await this.getLogs(this.screenLogLen) await this.$nextTick() next(false) },
项目开源地址:https://gitee.com/ckong/Zhimi.OpenSource.UniApp.TXIM.Vue
Uniapp开发交流群:755910061