iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 22
0
Modern Web

每日挖個坑,用坑填起耍廢聊天室!系列 第 22

二十二號坑,用ref抓取DOM之滑到最下面

現在每次發送訊息的時候,訊息區塊雖然會出現scrollbar,但都只會停在最上面,今天就來處理這件事r

因為我們需要抓到DOM的高度來做計算,會用到ref的屬性

  1. 把要抓取的DOM上下ref="name"
  2. 在vue裡用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頁做

計算滑到最下方
https://ithelp.ithome.com.tw/upload/images/20191008/20111962x83TozO8Mi.png

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')

上一篇
二十一號坑,用正規表達式寫指令
下一篇
二十三號坑,換頁就立刻focus!
系列文
每日挖個坑,用坑填起耍廢聊天室!30

1 則留言

0
King Tzeng
iT邦新手 4 級 ‧ 2019-10-08 13:57:41

你發文速度比我快了!!!/images/emoticon/emoticon04.gif

哼哼哼哼哼我剛寫好了明天的^.<
(但明天內容超少XD

我要留言

立即登入留言