+1

Tìm hiểu về $nextTick trong VueJS

Mình đã trải nghiệm VueJS được khoảng 3 tháng và khi hướng dẫn các bạn khác trong team tiếp cận Vue, có một số vấn đề mà ai cũng thấy khó hiểu, một trong số đó là $nextTick. Vậy hãy cùng tìm hiểu cách sử dụng $nextTick nhé.

$nextTick là gì ?

Theo định nghĩa trong doc của Vue:

Vue.nextTick( [callback, context] )

Defer the callback to be executed after the next DOM update cycle. Use it immediately after you’ve changed some data to wait for the DOM update..

Nghĩa là sao nhỉ? Cái gì xử lý sau cái gì hay gì gì đó. Lời giải thích này hơi mơ hồ. Nhưng đừng lo lắng vì định nghĩa khó hiểu này vì việc sử dụng Vue’s nextTick() là không phổ biến, mình đã viết nhiều component nhưng việc sử dụng Vue’s nextTick() khoảng tầm đôi ba lần. Tiếp theo đó, việc hiểu và sử dụng $nextTick sẽ dễ dàng hơn nếu có những ví dụ cụ thể.

Hiểu được $nextTick

Việc cần làm đầu tiên là chia nhỏ cái định nghĩa khó hiểu này.

Defer the callback

Ok, vậy nextTick nhận tham số đầu vào là callback, như sau:

Vue.nextTick(function () {
  // do something cool
})

Và callback này sẽ được xử lý khi nào nhỉ:

the next DOM update cycle.

Ok, chúng ta đều biết được rằng Vue cập nhật Dom theo cách bất đồng bộ. Vue có một cách để lưu trữ việc thay đổi DOM này cho đến khi chúng được áp dụng. Vue tạo ra một queue các update này và có thể xóa chúng khi cần. Sau đó, Vue update DOM lên phiên bản cao nhất theo queue. Tưởng tượng như thế này, khi trang web của bạn đã load xong hết DOM, và rồi một function nào đó sử dụng nextTick được gọi. Vue sẽ không render lại component một cách tự động, mà Vue sẽ chạy queue thay đổi DOM này, việc update DOM sẽ theo tuần tự qua đó hàng đợi được giải phóng.

Kết luận, chúng ta có thể sử dụng nextTick để xử lý callback function ngay sau khi dữ liệu và DOM được cập nhật. Việc luồng xử lý của chúng ta điều khiển việc render component của Vue là không cần thiết. Nhưng có một số trường hợp chúng ta cần phải đợi một element nào đó thay đổi, biến mất hay xuất hiện, đó là lúc chúng ta cần đến $nextTick.

Use it immediately after you’ve changed some data to wait for the DOM update.

Đây là phần cuối cùng của Vue doc. Bên trong callback, DOM đã được update nên chúng ta có thể thao tác được với phiên bản mới nhất của DOM.

Chứng minh

Dưới đây là đoạn code ví dụ của $nextTick

const example = Vue.component('example', {
  template: '<p>{{ message }}</p>',
  data: function () {
    return {
      message: 'not updated'
    }
  },
  mounted () {
    this.message = 'updated'

        console.log(
        'outside nextTick callback:', this.$el.textContent
    ) // => 'not updated'

    this.$nextTick(() => {
      console.log(
        'inside nextTick callback:', this.$el.textContent
      ) // => 'not updated'
    })
  }
})


new Vue({
  el: '#app',
    render: h => h(example)
})

Sử dụng

Hãy cố gắng xác định một số trường hợp sử dụng hữu ích cho nextTick.

Hãy tưởng tượng rằng bạn cần thực hiện một số hành động khi một element nào đó trong component được tạo ra, thay đổi, biến mất. NHƯNG! Không chỉ thành phần. Bạn cũng cần đợi cho đến khi tất cả các element được gắn kết và có sẵn trong DOM. Giá như chúng ta có một function cần được xử lý trong lần cập nhật DOM tiếp theo:

mounted() {
  this.$nextTick(() => {
    // The whole view is rendered, so I can safely access or query
    // the DOM. 
  })
}

Chi tiết

$nextTick là một cách thoải mái để thực thi một chức năng sau khi dữ liệu và DOM đã được cập nhật. Một số người cũng sử dụng nextTick trong unit test của họ như một cách để đảm bảo dữ liệu đã được cập nhật. Bằng cách này, họ có thể check được version mới nhất của component.

Dùng Vue.nextTick() hay vm.$nextTick()

Cả hai cái đều như nhau, Vue.nextTick được coi như API method toàn cục thì vm.$nextTick() là instance method. Sự khác biệt duy nhất là vm.$nextTick chỉ nhận một tham số.

Chú ý

$nextTick trả về Promise, nên bạn hoàn toàn có thể sử dụng async/await với chúng.

async mounted () {
    this.message = 'updated'
    console.log(this.$el.textContent) // 'not updated'
    await this.$nextTick()
    console.log(this.$el.textContent) // 'updated'
}

Qua bài viết này, mong các bạn có thể hiểu hơn về nextTick qua đó không còn cảm thấy khó khăn khi sử dụng chúng nữa.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí