Vue instance (Đối tượng Vue) trong Vue.js

Khi theo dõi bài viết Hello World trong Vue chắc hẳn các bạn sẽ bắt gặp đoạn code sau "new Vue" . Đây thực chất là đoạn code để khởi tạo một Vue instance, vậy Vue instance là gì chúng ta cùng tìm hiểu về nó trong bài viết đưới đây nhé!

Vue instance là gì?

Vue có thể coi như một lớp có tên gọi là Vue. Vì vậy Vue Instance (dịch là đối tượng Vue) cũng có thể coi là lớp đối tượng Vue. Một ứng dụng Vue luôn được bắt đầu bằng cách khởi tạo một đối tượng Vue (Vue Instance) sử dụng hàm Vue

Cú pháp hàm Vue để tạo đối tượng Vue như sau:

var vm = new Vue({
 // options (các tùy chọn) 
})

Khi khởi tạo một Vue Instance bạn cần truyền vào một object options (đối tượng tùy chọn) với các tùy chọn. Phần lớn bài học này sẽ mô tả cho bạn cách sử dụng các tùy chọn bạn cần truyền vào để tạo ra hành vi ( behavior) mong muốn. Ngoài ra bạn có thể tham khảo danh sách  đầy đủ các tùy chọn ở trang API Vue.

Một ứng dụng Vue bao gồm một đối tượng Vue gốc gọi là root Vue instance  được tạo ra bởi lệnh new Vue. Ứng dụng Vue cũng thường được sắp xếp thành một cây gồm các phần tử (component) lồng nhau và có thể tái sử dụng được. Ví dụ cây phần tử của một ứng dụng có dạng như sau:

Đối tượng gốc
└─ Những việc cần làm
     ├─ Danh mục cần làm
     │       ├─ Nút xóa công việc
     │       └─ Nút sửa công việc
     └─ Chân trang danh sách cần làm
              ├─ Nút làm sạch công việc
              └─ Thống kê danh sách công việc

Phần component sẽ được chúng mình trình bày ở sau, bạn chỉ cần biết rằng một component Vue cũng chính là một đối tượng Vue. Đây cũng chính là lý do nó nhận cùng một object options (trừ 1 số tùy chọn chỉ giành riêng cho đối tượng root)

Dữ liệu (Data) và phương thức (Methods)

Khi một Vue instance được khởi tạo tất cả các thuộc tính (property) được tìm thấy trong dữ liệu của đối tượng (object data) sẽ được thêm vào hệ thống phản ứng của Vue (gọi là reactivity system). Điều này nghĩa là View sẽ phản ứng (react) khi giá trị của các thuộc tính này thay đổi đồng thời tự cập nhật tương ứng với các giá trị mới cập nhật.

// Chúng ta khởi tạo một object "data"
var data = { a: 1 }


// Object này được truyền vào một đối tượng Vue
var vm = new Vue({
data: data
})


// Truy xuất đến thuộc tính của đối tượng 
// trả về giá trị của object "data" đã khởi tạo 
vm.a == data.a // => true


// Thay đổi thuộc tính của vm cũng
// ảnh hưởng đến dữ liệu ban đầu
vm.a = 2
data.a // => 2


// ... và ngược lại
data.a = 3
vm.a // => 3

Khi thay đổi dữ liệu, view sẽ hiển thị lại. Bạn cũng cần lưu ý rằng một thuộc tính trong dữ liệu đối tượng chỉ trở nên phản ứng nếu nó tồn tại khi chúng ta khởi tạo đối tượng Vue, có nghĩa là nếu bạn thêm vào một mới thuộc tính như sau:

vm.b='Cool'

thì những thay đổi với b sẽ không phản ứng hay thay đổi trên view. Vì vậy hãy nhớ trong đầu là nếu sau này bạn cần một thuộc tính nào đó nhưng khi khởi tạo Vue mà thuộc tính này sẽ là rỗng hoặc chưa tồn tại thì bạn cần gán cho nó một giá trị ban đầu.

Ví dụ như sau:

data: {
  newTodoText: '',
  visitCount: 0,
  hideCompletedTodos: false,
  todos: [],
  error: null
}

Có một ngoại lệ duy nhất khi sử dụng Object.freeze () bởi vì Object.freeze () ngăn không cho những thuộc tính có sẵn bị chỉnh sửa. Điều này có nghĩa là hệ thống phản ứng của Vue không thể theo dõi các thay đổi xảy ra

Code JS

var obj = {
  foo: 'bar'
}
Object.freeze(obj)
new Vue({
  el: '#app',
  data: obj
})

Code HTML

<div id="app">
  <p>{{ foo }}</p>
  <!-- this will no longer update `foo`! -->
  <button v-on:click="foo = 'baz'">Change it</button>
</div>

Ngoài data một đối tượng Vue cũng hỗ trợ một số thuộc tính và phương thức đối tượng (instance properties & methods) hữu dụng khác.  Để phân biệt với các thuộc tính và phương thức người đụng định nghĩa. Các thuộc tính và phương thức trên được bắt đầubằng ký hiệu $ . Ví dụ:

var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})

vm.$data === data // => true
vm.$el === document.getElementById('example') // => true

// $watch là một phương thức của đối tượng Vue
vm.$watch('a', function (newValue, oldValue) {
  // Hàm callback này sẽ được gọi khi 'vm.a' thay đổi
})

Bạn cũng có thể tham khảo danh sách đầy đủ các thuộc tính và phương thức đối tượng trên trang API của Vuejs.

Ví dụ về thuộc tính và phương thức trong Vuejs

var app = new Vue({
    el: '#app',
    data: {
        //thuộc tính
        message: 'hello world',
        // phương thức
        getSite : function () {
            return 'hoc.tv'
        }
    },
});

HTML viết :

<div id="app">
        <p>Message = {{ message }}</p>
        <p>Phương thức getSite trả về: {{ getSite() }}</p>
</div>

Kết quả như sau:

Instance Lifecycle Hook (Vòng đời của đối tượng Vue)

Khi được khởi tạo, một đối tượng Vue sẽ đi qua nhiều bước khác nhau - cài đặt quan sát dữ liệu (data observation), biên dịch template, gắn kết vào DOM, cập nhật DOM khi dữ liệu thay đổi v.v. Trong suốt tiến trình này, nó cũng sẽ thực thi một số hàm gọi là lifecycle hook, giúp người dùng thêm code của mình vào các giai đoạn (stage) cụ thể trong vòng đời của đối tượng. Hooks có thể được hiểu là các phương thức, các hàm được cung cấp sẵn, có thể can thiệp vào từng giai đoạn của vòng đời.

Ví dụ, hook created có thể được dùng để thực thi code sau khi một đối tượng được khởi tạo.

Ví dụ, hook created có thể được dùng để thực thi code sau khi một đối tượng được khởi tạo:

new Vue({
  data: {
    a: 1
  },
  created: function () {
    // `this` trỏ đến đối tượng Vue hiện hành
    console.log('giá trị của a là ' + this.a)
  }
})
// => "giá trị của a là 1"

Các hook khác như mounted, updated và destroyed cũng được gọi vào các đoạn khác nhau trong vòng đời của đối tượng. Tất cả các hook này đều được thực thi với ngữ cảnh trỏ This đến đối tượng Vue hiện hành.

Đừng dùng hàm mũi tên (arrow functions) cho các thuộc tính tùy chọn hoặc callback như là
created: () => console.log(this.a) hoặc vm.$watch('a', newValue => this.myMethod()).
Vì hàm mũi tên được bind vào ngữ cảnh cha (parent context), this sẽ không trỏ đến đối tượng Vue hiện hành. Do vậy this.a hoặc this.myMethod sẽ không trả về giá trị mà bạn mong đợi, mà thay vào đó thường là các lỗi Uncaught TypeError: Cannot read property of undefined hoặc Uncaught TypeError: this.myMethod is not a function. fff

Sơ đồ vòng đời của Vue instance

Dưới đây là sơ đồ vòng đời của một Vue instance (đối tượng Vue). Ngay lúc này thì bạn chưa cần hiểu mọi thứ trong đây, nhưng dần dần về sau khi bạn học và xây dựng thêm với Vue, sơ đồ này sẽ là một nguồn tham khảo rất hữu ích.

Trong vue.js có các scope event sau:

  • beforeCreate - được gọi khi chúng ta khởi tạo vue.js và trước khi thực hiện tiến trình observe Data và init Events.
  • created - được gọi khi tiến trình observe Data và init Events hoàn thành.
  • beforeMount - được gọi ngay sau khi tiến trình render function hoàn tất.
  • mounted - được gọi khi tiến trình replace el hoàn tất.
  • beforeUpdate - được gọi khi data có sự thay đổi, và trước khi visualDOM re-rendered.
  • updated - được gọi khi data đã được thay đổi.
  • beforeDestroy - được gọi ngay trước khi vue instance được destroy.
  • destroyed - được gọi khi vue instance đã được destroy.


Bình luận