現在每次發送訊息的時候,訊息區塊雖然會出現scrollbar,但都只會停在最上面,今天就來處理這件事r
因為我們需要抓到DOM的高度來做計算,會用到ref
的屬性
ref="name"
this.$refs.name
就可以抓到DOM嚕在nuxt的
asyncData
中是抓不到ref的,因為執行asyncData時,DOM尚未被渲染出來,所以抓不到
<div
class="chat_main"
ref="chat_main"
>
<div class="channel_tab">...</div>
// ...略
</div>
如果切版是延續十號坑,需要改一下切法Orz,因為要抓的DOM在原本的寫法會在layout那層,為了容易讀,所以我把這塊切版改到chat頁做
計算滑到最下方
scrollBottom() {
let dom = this.$refs.chat_main
dom.scrollTop = dom.scrollHeight - dom.clientHeight
}
然後在更新對話資料之後執行
uploadMsg(msg) {
this.allMsg.push(msg)
this.scrollBottom()
},
雖然理論上是這樣沒錯,但這邊會遇到一個問題,就是執行scrollBottom的時候抓到的DOM高度還是舊的,我們的對話內容是v-for渲染出來,但執行速度上,v-for還沒渲染完,scrollBottom就去抓了高度,所以計算出來會少一次對話的高度
目前為了要確認是在畫面渲染之後才執行scrollBottom,我改在對話component:codeClassFunc跟codeClassHtml的mounted去觸發,也就是當對話被建立之後才觸發,不過還需要另外處理一些東西,像是當是別人發的對話的時候不觸發,只有自己發的訊息才觸發之類的
然後因為改到子層才觸發,所以需要用到$emit
先在templete綁定事件
<div
v-for="chat in channels.now.msg"
:key="chat.key + chat.text"
>
<component
:is="chat.codeClass"
:text="chat.text"
:name="chat.name"
@scrollBottom="scrollBottom" // 將scrollBottom綁上去
/>
</div>
然後再下一層就可以用emit
去觸發上一層的事件
this.$emit('scrollBottom')