文章概述上次我们讨论了聊天输入框的实现,实现文字、语音、标签的编辑发送,而这次我们的重点又会回到整个聊天界面容器的实现上。聊天界面容器的实现一、为什么要实现聊天界面容器一般情况下,开发者会直接在对应的界面中实现聊天界面UI进行开发。这种开发思路无可厚非,但是如果我们要实现跨平台的聊天IM,那么就不可避免地会遇到组件之间的事件冲突和多平台之间的性能差距,尤其是在聊天方面。我们还需要实现滚动加载。如果我们在每个界面实现一套代码,会导致整体代码的可维护性下降,所以我们有必要实现一个聊天界面容器来显示消息,滚动加载,长按菜单,输入、编辑等兼容处理都在这里完成,实现界面和业务组件的解耦。2.聊天界面容器的设计聊天界面容器的设计非常简单。下面整理一下需要实现的功能。滚动到底部输入法高度自适应滚动加载2.1滚动到底部首先我们要确定我们的聊天界面是必须滚动的,接收/发送消息需要在底部滚动,类似下面的效果在微信上发送和接收消息。我们确定组件只能使用scrollView。具体实现如下实现滚动到底部,一般来说只能用ScrollTop,并且为了兼容nvue,我们使用weex的原生dom模块获取可滚动高度——容器的高度可以实现可滚动高度。asyncscrollToBottom(retouchCount){if(this.inUpperLoading||this.scrollBottoming){return}this.scrollBottoming=true//awaitthis.$nextTick()//this.$utils.delay(100)//让view=awaitthis.$utils.query(this,'.chat-layout__scroll')//this.scrollTop=view.scrollHeight//nvue必须使用下面的awaitthis.$nextTick()dom.scrollToElement(this.$refs.ending,{动画:false})this.scrollBottoming=falseawaitthis.$nextTick()retouchCount=retouchCount||0retouchCount++//最多5次重新滚动到测试底部,nvue下渲染,nextTick后100%正常dom.getComponentRect(this.$refs.scroll,({size})=>{let{detail}=this.scrollEventif(!detail){this.scrollTop=0if(retouchCount<5){this.scrollToBottom(retouchCount)}}else{this.scrollTop=detail.scrollHeight-size.height//console.log('repositionscrollTop')if(retouchCount<5){this.scrollToBottom(retouchCount)}}})}2.2输入法高度自适应一般情况下,在vue界面,我们输入焦点后,会自动适应输入法的高度。但是在nvue中,当我们的界面中嵌套了一个视频播放器的时候,输入的高度会计算错误,所以我们需要手动监听输入法的高度变化,然后做一个自适应收缩的界面容器就可以了uni.onKeyboardHeightChange(this.onKeyboardHeightChange)//asynconKeyboardHeightChangeinmethods({height}){this.paddingBottomHeight=heightawaitthis.$nextTick()height&&this.scrollToBottom()},2.3滚动加载实现滚动加载的方式有很多种,这里我们只简单实现一种,监听scrollView的scrolltoupper事件判断是否加载,然后抛给业务层控制滚动加载。onScrollToUpper:throttle(asyncfunction(){if(this.inUpperLoading||this.disableUpperLoading||this.end){return}this.inUpperLoading=trueletoldChildrens=this.$refs.scroll.children.lengththis.$emit('upperLoading',asyncisEnd=>{if(isEnd){this.disableUpperLoading=true}等待this.$nextTick()让newChildrens=this.$refs.scroll.children.lengththis.inUpperLoading=false让refEl=this.$refs.scroll.children[newChildrens-oldChildrens]dom.scrollToElement(refEl,{animated:false})})},200,{leading:true,trailing:false}),而对于业务层来说,在收到upperLoading事件后,做数据加载,然后反馈加载完成asyncloadMoreLog(next){console.log('loadMoreLog')awaitthis.getLogs(this.screenLogLen)awaitthis.$nextTick()next(false)},项目开源地址及交流群项目成品效果查看:项目介绍项目开源地址:https://gitee.com/ckong/Zhimi...Uniapp开发交流群:755910061