一、問題描述
首次進入聊天窗口,數據加載之后先顯示最早消息,后顯示最新消息,也就是數據加載完之后,延遲了一個時間滾動條才自動定位到最底部。
二、解決方案
如果數據在剛好加載完的時候滾動條就定位到了最底部就好了,就不會在進入聊天窗口之后還看到滾動條在往下滾動,出現的問題就是因為獲取數據和設置滾動條位置的代碼不是同步的不是按順序執行的,后者加了定時器。
像微信聊天窗口一樣,一進入到聊天窗口就看到滾動條是在聊天窗口的最底部。
聊天窗口是一個組件,調起的不同的用戶的聊天窗口都是這一個聊天窗口組件。
聊天窗關鍵代碼:
created() { bus.$on('getMessageData', (user)=> { this.userObj = JSON.parse(JSON.stringify(user)) if(user && !user.id) { console.error("有問題userObj.id為:", user.id) } this.messageList = [] this.$nextTick(()=> { setTimeout(() => { this.scrollContainer = document.querySelector('.chat-window-content') this.getUserToAssistantInfo() .then(() => { return this.getUserInfoList(user) }) this.refresh(user) }, 100); }) }) }
async getUserInfoList(user) { return apis.getWxMessageData({user_id: user.id}).then(({data:{index, messages}}) => { this.index = index || '' this.messageList = messages || [] this.$nextTick(() => { let el = this.scrollContainer el.scrollTop = el.scrollHeight-el.clientHeight // console.log(el, el.scrollTop, el.scrollHeight, el.clientHeight) }) }) }
注意3個關鍵點:
1、確保總是能拿到滾動區域的外層元素,用來定位滾動條的位置,也就是一定要在dom渲染能拿到dom元素再讀取元素。
2、在能拿到這個元素的情況下,去獲取聊天內容。
3、確保在獲取到數據並渲染之后立即設置滾動條到最底部。
因為vue中dom數據的更新是異步的,vue中當觀察到數據變化時,會開啟一個隊列,也就是最終數據的刷新會在下一個事件循環Tick中去執行。所以在獲取到聊天內容之后,要立即更新滾動條的位置,必須放在nextTick中去執行設置滾動條位置的代碼。
類似問題參考:
vue踩坑日記之$nextTick:
https://www.jianshu.com/p/d6cbcb0904c8?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
簡單理解vue中的nextTick:
https://juejin.im/post/5a6fdb846fb9a01cc0268618