uni-app插件开发,uni-app插件

  

  最近工作重心转移到了uniapp。有一种说法是,这个框架在跨端方面真的很优秀,一套代码可以一次性编译,多端使用。   

  

  然而随之而来的是层出不穷的兼容性问题。同样,似乎也无法应对APP底层的变化。与此同时,uniapp的性能问题也饱受诟病。这方面,一是要提高自己的编码能力,二是要依靠dcloud团队不断优化框架。   

  

  这期是和大家分享一下用uniapp开发聊天APP时踩坑的问题。   

  

     

  

  首先,输入框吞字,光标闪烁。在uniapp中使用输入框时有一个问题,无论是input组件还是textarea组件。   

  

  如果组件被绑定到v-model,将会有两个bug:   

  

  输入时,苹果手机上的输入框会出现吞字或者使用一些特殊区域的输入法进行选择;   

  

  从文本中间进入时,光标会闪烁到末尾。   

  

  解决这个问题只能用:value绑定输入框,给输入框赋两个变量,一个是实值,一个是临时tempValue。   

  

  的临时tempValue用于在输入触发的@input事件期间实时接收。实值只在第一次从无值变为有值时接收一次,然后发送时将实值设置为null即可清空输入框。   

  

  textarea : value=' value ' @ input=' handle input '/textarea button @ click=' handle click send ' send/button/template export default { data : { value : ' ',tempvalue : ' ' } handle input(event){ const value=event . detail . value if(!This.value) {//第一个值为空时,赋给实值this . value=value } this . temp value=value//临时值用于接收} asynchandleClickSend() {if(!This.value) {return} //发送时,将临时值存储为当前输入框中的值。//然后将实值value设置为null清空输入框。//模拟发送请求constres=await this。$ axios . post({ URL 3360 XXX,text 3360 this . temp value })this . value=' '//   

  

  二、组件键值问题Blogger封装了一个消息气泡渲染组件,只需要传入必要的参数就可以渲染各种消息。但在开发过程中发现了气泡消息抛出后长按事件导致参数混乱的问题,经研究后通过在组件中添加键值的方式解决。   

  

  模板view class=' chat-warp ' v-for=' item of msgList ' : key=' item . id '!-请注意,您还需要为组件提供键值-chat-item : item=' item ' 3360 key=' item . id '/chat-item/view/template。可能是vue中组件的更新机制不同,所以v-for循环中的组件也需要给出键值。   

  

  第三,消息定位问题项目中的聊天页面使用scroll-view来呈现各种封装了富文本组件的消息。由于当更多的消息被下载时,屏幕总是会闪烁,所以最后两层滚动视图一起使用,一层是真消息,另一层是假消息。   

  

  加载更多时,显示假消息,隐藏真消息,然后在消息完全渲染定位后,隐藏假消息,显示真消息。   

  

  (1)滚动不到最底部的问题   

  

  在开发过程中,经常会遇到发消息或进入聊天页面时,无法滚动到底部的情况。   

  

  解决这个问题,刚开始的时候是不断滚动到底部,一进入页面就会触发七八次goBottom功能。   

  

  优化后,我整理了一下思路,调整为“判断消息是否完整渲染。”   

后,再执行goBottom 函数”。

  

而判断消息是否完全渲染完毕,则需要用到 uni.createSelectorQuery() 这个 API。

  

// 在onReady钩子中调用goBottomonReady() { this.$nextTick(() => { this.goBottom() })}// 滚动到底部函数goBottom() { this.scrollView = '' // scrollview瞄点置空 this.$nextTick(async () => { const res = await this.checkMsgIsRender('btm') // 检测最底部的消息是否完全渲染完毕 if(res) { this.scrollView = 'bottom' // 瞄点至底部 } else { this.goBottom() } })}// 检测消息是否渲染完毕checkMsgIsRender(position) { let msgID = '' if(position === 'btm') { // 底部 // 找到最底部的消息ID msgID = xxxx } else { // 顶部 // 找到最顶部的消息ID msgID = yyyy } // 返回一个Promise return new Promise((resolve) => { const query = uni.createSelectorQuery().in(this) query.select('#id').boundingClientRect(data => { // 存在data,且存在宽和高,视为渲染完毕 if(data && data.width && data.height) { resolve(true) } else { resolve(false) } }).exec(); })}(2)下拉加载更多消息瞄点定位不准的问题

  

同样地,“下拉加载更多消息”也是存在瞄点不准确的问题,而一开始的解决方案,是简单粗暴地延时两秒钟,这直接导致了用户出现等待时间过长的问题,而且还不一定能准确定位到。

  

参照滚动到底部的做法,我们举一反三,通过判断消息是否完全渲染完毕来决定瞄点的时机,以确保瞄点定位准确。

  

// 加载更多async loadMore() { await this.getMoreMsg() // 向服务器获取更多消息或者展示本地消息,该函数不展开 let location = async () => { const res = await this.checkMsgIsRender('top') // 检测最顶部的消息是否完全渲染完毕 if(res) { // 这里还需要找到需要瞄点过去的消息ID,zzzz this.scrollView = zzzz // 瞄点到消息zzzz } else { location () } } this.scrollView = '' // scrollview瞄点置空 this.$nextTick(() => { location () })}总结虽然网上对 uniapp 一直存有质疑的声音,但是讲句道理,能够以一套代码运行到多端的技术还是挺厉害的,尽管目前来说这项技术还不是很成熟(性能问题、兼容问题)。
uniapp 能带领我们的项目走向多远,还是可以期待的,当然不能光指望 dcloud 团队,个人代码的写法也很关键,一起继续努力,Keep learning…

  


  

下期继续给大家分享uni-app实战中的点点滴滴,敬请期待~

  

欢迎各位关注、留言,大家的支持就是我的动力!

相关文章