iT邦幫忙

2023 iThome 鐵人賽

0
Vue.js

從0開始學習30天可以到什麼程度?系列 第 27

No27: 狀態更新與同步

  • 分享至 

  • xImage
  •  

這裡是前面那部分的一個小番外,再處理實體的狀態同步到DOM的時候雖然我們一直在說"同步"更新,但在執行上它還是非同步的,當setter偵測到需要更新的狀態時會將事件加入到一個排隊queue中,我們可以用這個例子來看

<div id="app">
  <p>
    messages: {{ messages }}
  </p>

  <p>
    scrollHeight: {{ scrollHeight }} <br>
    DOM 實際的 scrollHeight: {{ realScrollHeight }}
  </p>

  <div class="messages">
    <div v-for="m in messages">{{ m }}</div>
  </div>

  <input type="text" placeholder="輸入任意文字後按下 enter 鍵" v-model.trim="msg" @keydown.enter="addToMessages">
</div>
const vm = Vue.createApp({
  data: () => {
    return {
      msg: '',
      scrollHeight: 0,
      realScrollHeight: 0,
      messages: ['Hello', 'Vue.js', '好棒棒']
    }
  },
  methods: {
    addToMessages() {
      this.messages.push(this.msg);
      this.msg = '';

      const el = document.querySelector('.messages');
      this.scrollHeight = el.scrollHeight;
      el.scrollTop = el.scrollHeight;

      this.$nextTick(() => {
        this.realScrollHeight = el.scrollHeight;
      });
    }
  },
  mounted() {
    const el = document.querySelector('.messages');
    this.realScrollHeight = el.scrollHeight;
    this.scrollHeight = el.scrollHeight;
  }
});


vm.mount('#app');

這個程式是我們希望在user輸入完成後按下enter鍵,會將文字data新增到一個文字陣列當中,並且讓畫面自動移動到最底端來顯示最新加入的訊息,上面的addToMessage()就是這個功能,但上面這樣的寫法雖然看起來沒問題,執行起來卻發現它始終會滑到和最後一行有一行差距的位置,這就是因為狀態與畫面的更新"不同步"的原因,它在新的文字被加到畫面之前就先偵測高度,自然得到的結果會是上一行,這個問題只要加上vm.$nextTick(),就可以確保它會等到畫面的更新都結束了才執行。


上一篇
No26: Vue實體生命週期
下一篇
No28: 元件系統
系列文
從0開始學習30天可以到什麼程度?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言