Cơ bản về Vue instance

Trong 10 bài đầu tiên của Khóa học Vue.js miễn phí, hầu hết các đoạn code trong các ví dụ chúng ta đều lặp lại những cú pháp kiểu như new Vue({ … }) nhưng chúng ta đều tạm ngầm định với nhau rằng cần phải có cú pháp đấy Vue.js mới hoạt động được. Điều này cũng hết sức bình thường, ứng dụng cần các instance (thực thể) từ các đối tượng trước khi hoạt động.

Thuật ngữ instance trong lập trình thường được giữ nguyên vì dịch sang tiếng Việt rất khó, có thể tạm dịch là một thể hiện, một thực thi hay một thực thể của một lớp (class). Nhân tiện chúng ta cùng nhau nói về các khái niệm class, object và instance để hiểu tường tận hơn. Class (lớp) giống như một bản thiết kế nhà chẳng hạn, chúng ta sử dụng bản thiết kế này để xây các ngôi nhà cụ thể là các instance hay thể hiện cụ thể của bản thiết kế. Các đối tượng (object) này giống nhau về khung (số tầng, cầu thang ở giữa…) nhưng khác nhau về nét đặc trưng (màu sơn, chất liệu cửa…).

1. Cú pháp khởi tạo Vue instance

Từ thảo luận ở trên chúng ta có Vue instance là một thể hiện hay một thực thể của lớp Vue. Mọi ứng dụng sử dụng framework Vue.js đều phải bắt đầu bằng việc khởi tạo Vue instance với cú pháp như sau:

<div id='app'>
  <h1>{{ message }}</h1>
</div>
<script>
  var vm = new Vue({
    el: '#app',
    data: {
       message: 'Xin chào, tôi là Vue.js!'
    },
    methods: {
       ...
    }
  })
</script>

Vue.js được thiết kế hướng theo mô hình MVVM, quy ước sử dụng biến vm (viết tắt ViewModel) để tham chiếu đến một thực thể Vue. Khi khởi tạo một thực thể Vue, bạn cần truyền cho nó một đối tượng chứa các thuộc tính. Các thuộc tính này có nhiều các nhiệm vụ khác nhau trong ứng dụng:

  • data chứa dữ liệu
  • template chứa mã các phần tử được viết riêng
  • methods chứa các phương thức được sử dụng trong ứng dụng.
  • các phương thức được kích hoạt trong vòng đời của thực thể Vue.

2. Xác định phần tử HTML cần xử lý qua thuộc tính el

Chúng ta cùng xem chi tiết hơn đoạn code mẫu khởi tạo thực thể Vue ở trên. Đầu tiên là thuộc tính el của Vue instance để xác định thành phần HTML nào sẽ được thực thể Vue này kiểm soát hay nói một cách khác là phần tử HTML nào được thực thể Vue gắn vào (mount), như vậy bằng cách khai báo với thuộc tính el, Vue instance sẽ được mount tự động vào một phần tử HTML.

Khi chạy code trong phần 1 của bài viết bạn sẽ thấy biến message trong cú pháp {{ }} được hiển thị thàunh chuỗi ‘Xin chào, tôi là Vue.js!’, tại thời điểm đó Vue instance không còn kiểm soát phần tử #app, nó ở trạng thái unmounted. Chúng ta có thể sử dụng phương thức $mount() trên Vue instance để thực hiện gán nó vào một phần tử HTML.

vm.$mount('#app');

Nó hoàn toàn giống với việc bạn sử dụng thuộc tính el vậy. Bạn cũng có thể truyền trực tiếp đối tượng DOM vào phương thức $mount():

vm.$mount(document.getElementById('app'));

Phương thức $mount() hữu ích trong trường hợp tại thời điểm khởi tạo Vue instance bạn chưa biết mount nó vào đâu.

3. Dữ liệu cho view

Tất cả dữ liệu bạn định gán lên view cần được khai báo và trả về trong hàm data. Cách viết

data: {
   message: 'Xin chào, tôi là Vue.js!'
},

là viết tắt trong ES6, viết một cách đầy đủ như sau:

data: function () {
   return {
       message: 'Xin chào, tôi là Vue.js!'
   }
},

Hàm data trả về một đối tượng, mỗi thuộc tính của đối tượng có thể lại là một đối tượng có thể được gán lên view hoặc truy xuất trong code Javascript thông qua biến this. Ví dụ khi cần thiết lập giá trị cho message chúng ta có thể thực hiện như sau:

this.message = 'Khóa học Vuejs miễn phí.';

Bạn cũng hoàn toàn có thể khai báo các đối tượng từ trước và khi khởi tạo thực thể Vue thì mới đưa đối tượng đó vào phần trả về của hàm data.

var data = { message: 'Xin chào, tôi là Vue.js!' }
var vm = new Vue({
  data: data
})
vm.message === data.message // Cho kết quả true
// Thiết lập giá trị cho thuộc tính cũng ảnh hưởng đến đối tượng gốc
vm.message = 'Giới thiệu Vue.js'
data.message // Có giá trị là 'Giới thiệu Vue.js'
// và ngược lại
data.message = 'Công cụ lập trình với Vue.js'
vm.message // Có giá trị là 'Công cụ lập trình với Vue.js'

4. Các phương thức

Khi viết các ứng dụng, chúng ta cần có nhiều các phương thức để có thể sử dụng lại được ở nhiều nơi. Trong Vue.js các phương thức được viết trong thành phần methods của Vue instance, nó có thể được gọi từ trên view hoặc trong các đoạn code Javascript khác. Cũng có thể gán một phương thức với một sự kiện qua câu lệnh v-on để quản lý các hành động khi sự kiện xảy ra.

<button type="button" class="btn btn-outline-primary" v-on:click="like">
    <i class="far fa-thumbs-up"></i> Thích <span class="badge badge-pill badge-primary">{{ likes }}</span>
</button>
...
methods: {
    like: function () {
        if (this.lastClickTime === null || moment().diff(moment(this.lastClickTime), 'seconds') > 10) {
            this.likes ++;
            this.lastClickTime = moment().format();
            this.alert = false
        } else {
            this.alert = true;
        }
    }
}

Ví dụ này trong bài Quản lý sự kiện dễ dàng với v-on, trong bài này mặc dù chưa học đến các phương thức trong methods nhưng chúng ta cũng ngầm định là khai báo ở đây.

Những chỗ nào cần xử lý thêm like bạn có thể gọi đến phương thức like().

5. Các vấn đề khác trong Vue instance

Vue instance còn có rất nhiều các thành phần khác, trong phần này chúng ta sẽ chỉ giới thiệu sơ qua, các thành phần này sẽ có những bài chi tiết, nó rất quan trọng để bạn có thể áp dụng cho các dự án sau này.

  • computed: cho phép khai báo các phương thức trả về giá trị giống như methods nhưng chỉ tính toán lại khi có thay đổi, các phương thức trong methods thì luôn được tính toán lại mỗi lần gọi.
  • watch: khai báo các phương thức trả về giá trị phụ thuộc các biến khác và tự động cập nhật khi các biến đó thay đổi.
  • template, component: tạo các thành phần có thể sử dụng lại giúp xây dựng những hệ thống lớn.
  • các phương thức được kích hoạt (hook) trong các sự kiện xảy ra trong vòng đời của Vue instance.

Chúng ta cùng tìm hiểu sơ qua về hook là cơ chế can thiệp vào một chuỗi các hành động nhằm thực thi các logic riêng hoặc ngăn chặn sự kiện được hook xảy ra. Mỗi thực thể Vue có một loạt các bước khởi tạo, như thiết lập theo dõi dữ liệu, biên dịch template, mount thực thể vào DOM và cập nhật DOM khi data thay đổi. Xuyên suốt quá trình này, có thể can thiệp vào bằng các hook để thực thi các logic người dùng. Ví dụ created hook được gọi sau khi một thực thể được tạo ra:

var vm = new Vue({
  data: {
    a: 1
  },
  created: function () {
    // `this` points to the vm instance
    console.log('a is: ' + this.a)
  }
})
// -> "a is: 1"

Ngoài ra còn có rất nhiều các hook khác được gọi tại các giai đoạn khác nhau trong vòng đời một thực thể như mounted, updated, destroyed. Các hook này được sử dụng trong các ngữ cảnh khác nhau. Trong Vue.js không có khái niệm controller mà các logic tùy chỉnh của bạn cho một component sẽ được đưa vào các hook khác nhau trong vòng đời thực thể.

5.1 Sơ đồ vòng đời thực thể

Trong sơ đồ này có thể bạn không hiểu hết tường tận, nhưng có thể nó có ích cho bạn trong tương lai.

Sơ đồ vòng đời thực thể

5.2 Truy nhập đến Vue instance từ bên ngoài

Chúng ta có thể làm mọi thứ trong thực thể Vue, tuy nhiên khi tích hợp với một số các thư viện có sẵn nào đó trên hệ thống, việc truy cập Vue instance từ bên ngoài là rất cần thiết. Chúng ta cùng xem xét ví dụ sau đây:

<!DOCTYPE html>
<html>
<head>
    <title>Vue instance - allaravel.com</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
    <div id="app">
        <p>{{ message }}</p>
    </div>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                message: 'Tài liệu Khóa học Vuejs miễn phí sẽ được hiển thị sau 3 giây!'
            },
            methods: {
                alertUser: function (){
                    alert('Nhấp ok để tải tài liệu!');
                }
            }
        });
        setTimeout(function (){
            vm.alertUser();
            vm.message = 'Click vào đây để tải!';
        }, 3000);
    </script>
</body>
</html>

Trong ví dụ này chúng ta đã gọi đến phương thức được khai báo trong thực thể Vue, ngoài ra chúng ta cũng thay đổi cả dữ liệu của Vue instance. Cách truy xuất là trực tiếp mà không cần các tiền tố như ở phần tiếp theo là bởi vì Vue đã tạo ra các hàm ủy quyền (proxy function) ở trung gian để gọi đến dữ liệu cần truy cập ở sau.

Proxy function in vue

5.3 Sử dụng nhiều Vue instance

Bạn hoàn toàn có thể tạo ra nhiều Vue instance trong cùng một trang mà mỗi instance sẽ được mount vào một thành phần nào đó trong trang. Cách này rất hữu ích cho việc thêm các công cụ vào trang, ví dụ một vue instance phục vụ cho phần form liên hệ ở giữa trang trong khi một Vue instance khác điều khiển hệ thống menu.

<div id="vm1">
  <h1>{{ name }}</h1>
</div>
<div id="vm2">
  <button @click="showName">Show name</button>
</div>
var vm1 = new Vue({
	el: '#vm1',
	data: {
		name: 'Vue Instance #1'
	}
});

var vm2 = new Vue({
	el: '#vm2',
	methods: {
		showName: function() {
			alert("The name of the other Vue instance is: ");
		}
	}
});

setTimeout(function() {
	vm1.name = 'Hello from the other side!';
}, 2000);

5.4 Các thuộc tính, phương thức đặc biệt của Vue instance

Vue instance còn có các thuộc tính và phương thức hữu ích khác, chúng được đặt trước bởi dấu $ để phân biệt với các thành phần cơ bản ở trên, ví dụ $data, $el, $mount(), $watch()…

var data = { a: 1 }
var vm = new Vue({
  el: '#example',
  data: data
})
vm.$data === data // -> true
vm.$el === document.getElementById('example') // -> true
// $watch is an instance method
vm.$watch('a', function (newVal, oldVal) {
  // this callback will be called when `vm.a` changes
})

5.5 Hủy bỏ một thực thể Vue

Thông thường việc hủy bỏ một thực thể là công việc của hệ thống nhằm dọn dẹp tài nguyên đã sử dụng, công việc này thường nằm trong các sự kiện được kích hoạt trong vòng đời của một thành phần, tuy nhiên đôi khi bạn muốn thực hiện hủy bỏ một Vue instance bằng tay, không có gì quá phức tạp:

<!DOCTYPE html>
<html>
<head>
    <title>Vue instance - allaravel.com</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
    <div id="app">
        <h1>Bộ đếm: {{ counter }}</h1>
        <button @click="counter++">Tăng bộ đếm</button>
    </div>
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <script type="text/javascript">
        var vm = new Vue({
            el: '#app',
            data: {
                counter: 0
            },
        });
        setTimeout(function() {
            alert('Hủy Vue instance, không thể tăng bộ đếm được nữa!');
            vm.$destroy();
        }, 5000);
    </script>
</body>
</html>

Trong ví dụ này bạn có thể bấm vào nút “Tăng bộ đếm” để tăng bộ đếm thêm 1, nhưng sau 5 giây khi code hủy Vue instance được thực hiện, nút “Tăng bộ đếm” cũng mất tác dụng.

6. Bài tập

Vận dụng các kiến thức trong bài Vue instance và các cú pháp cơ bản của Vue.js như v-if, v-for, v-on, v-bind, v-model, bạn hãy viết một ứng dụng quản lý công việc. Mỗi công việc là một đối tượng có các thuộc tính như sau:

  • Tiêu đề công việc
  • Chi tiết về công việc
  • Độ ưu tiên có 5 cấp độ
  • Trạng thái công việc: đã hoàn thành và chưa hoàn thành.

Phần code của ứng dụng mình sẽ cập nhật trong những bài sắp tới, hãy cố gắng thực hiện, nếu gặp vấn đề gì khó khăn, hãy cho mình biết trong phần comment cuối bài. Mọi người sẽ giúp bạn thực hiện.

Ứng dung quản lý công việc viết bằng Vue.js

7. Lời kết

Kiến thức cơ bản về Vue instance có rất nhiều những khái niệm mới, có thể bạn chưa thể nắm hết được cũng không sao vì các khái niệm này sẽ còn được nhắc tới chi tiết hơn trong các phần tới. Các kiến thức cần ghi nhớ duy nhất trong phần này là bạn cần khởi tạo thực thể Vue mỗi khi sử dụng Vue.js, thứ hai là cần phải gắn Vue instance với một thẻ HTML thông qua thuộc tính el, thứ ba là các dữ liệu cần hiển thị trên view (giao diện) cần khai báo thông qua thành phần data, thứ tư là các phương thức bạn có thể viết trong thành phần methods. Ok, như vậy bạn đã có thể trả lời được câu hỏi Vue instance là gì?

5 thoughts on “Cơ bản về Vue instance

Add Comment