Giới Thiệu Về Phản Ứng Trong Vue.js
Phản ứng (Reactivity) là một trong những tính năng quan trọng nhất của Vue.js, cho phép giao diện người dùng tự động cập nhật khi dữ liệu thay đổi. Bài viết này sẽ giải thích chi tiết về cơ chế hoạt động của phản ứng trong Vue.js, đặc biệt là với Composition API.
Khai Báo Trạng Thái Phản Ứng (Reactive State)
Để khởi tạo trạng thái phản ứng trong Composition API, bạn có thể sử dụng hàm ref()
. Ví dụ:
javascript
import { ref } from 'vue'
const count = ref(0)
Hàm ref()
sẽ nhận vào một giá trị và trả về dạng gói trong một đối tượng ref
. Đối tượng này có thuộc tính .value
để bạn có thể truy cập giá trị phản ứng. Chẳng hạn:
javascript
const count = ref(0)
console.log(count) // { value: 0 }
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
Như bạn thấy, đối tượng giá trị phản ứng được định nghĩa bằng biến count
. Để truy cập các giá trị này trong template của component, bạn cần khai báo và trả về chúng từ hàm setup()
. Ví dụ:
javascript
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return {
count
}
}
}
html
<div>{{ count }}</div>
Khi sử dụng setup
, bạn không cần dùng .value
để truy cập biến phản ứng đó.
Lưu ý: setup
là một hook quan trọng dành riêng cho Composition API, và tôi sẽ giải thích chi tiết về nó trong bài viết khác.
Bạn cũng có thể thay đổi giá trị của một tham chiếu trong trình xử lý sự kiện:
html
<button @click="count++">
{{ count }}
</button>
Xử Lý Logic Phức Tạp Và Giới Thiệu Script Setup
Với các logic phức tạp hơn, bạn có thể không cần phải định nghĩa nhiều hàm cho trình xử lý sự kiện. Ví dụ:
javascript
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
function increment() {
count.value++
}
return {
count,
increment
}
}
}
Và sử dụng hàm này trong template:
html
<button @click="increment">
{{ count }}
</button>
Nếu muốn thử nghiệm, bạn có thể kiểm tra trên Codepen.
Bây giờ, chúng ta sẽ xem xét script setup
, một cách tiếp cận khác hiệu quả hơn. Thay vì sử dụng setup
, bạn có thể sử dụng script setup
như sau:
html
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<template>
<button @click="increment">
{{ count }}
</button>
</template>
Tại Sao Nên Sử Dụng Refs?
Nhiều người có thể thắc mắc tại sao chúng ta lại cần những tham chiếu với .value
thay vì sử dụng biến thông thường. Để làm sáng tỏ điều này, cần hiểu cách thức hoạt động của hệ thống phản ứng trong Vue.
Khi tham chiếu được sử dụng trong template và giá trị của nó thay đổi, Vue sẽ tự động phát hiện thay đổi này và cập nhật DOM theo đúng. Khi component được khởi tạo lần đầu, Vue sẽ theo dõi mọi tham chiếu đã được sử dụng. Khi một tham chiếu bị thay đổi (mutate), Vue sẽ kích hoạt quá trình re-render cho các component liên quan.
Thuộc tính .value
giúp Vue theo dõi khi nào một ref
được truy cập hoặc thay đổi. Dưới đây là cách mà Vue quản lý:
javascript
const myRef = {
_value: 0,
get value() {
track()
return this._value
},
set value(newValue) {
this._value = newValue
trigger()
}
}
Phản Ứng Sâu (Deep Reactivity)
Refs có thể chứa bất kỳ loại giá trị nào, bao gồm cả các đối tượng lồng sâu, mảng hoặc các cấu trúc dữ liệu tiêu chuẩn của JavaScript như Map.
Một ref
sẽ đảm bảo rằng giá trị của nó có tính phản ứng sâu. Điều này có nghĩa là bạn có thể mong đợi các thay đổi sẽ được phát hiện ngay cả khi bạn thay đổi các đối tượng hoặc mảng ở bên trong:
javascript
import { ref } from 'vue'
const obj = ref({
nested: { count: 0 },
arr: ['foo', 'bar']
})
function mutateDeeply() {
obj.value.nested.count++
obj.value.arr.push('baz')
}
Sử Dụng reactive()
Ngoài ra, bạn cũng có thể sử dụng reactive()
để khai báo trạng thái phản ứng. Khác với ref
, reactive()
làm cho chính đối tượng trở nên phản ứng:
javascript
import { reactive } from 'vue'
const state = reactive({ count: 0 })
Sử dụng trong template:
html
<button @click="state.count++">
{{ state.count }}
</button>
Vue có khả năng chặn quyền truy cập và thay đổi tất cả các thuộc tính của một đối tượng reactive để theo dõi và kích hoạt reactivity.
Hạn Chế Của reactive()
API reactive()
cũng có một số hạn chế:
- Không hỗ trợ các kiểu dữ liệu nguyên thủy như string, number hoặc boolean.
- Không thể thay thế toàn bộ đối tượng, bởi vì việc theo dõi reactivity hoạt động dựa trên quyền truy cập thuộc tính, nên cần duy trì liên kết với đối tượng
reactive
ban đầu.
javascript
let state = reactive({ count: 0 })
// reference cũ không được theo dõi nữa
state = reactive({ count: 1 })
- Không thân thiện với việc hủy cấu trúc (destructuring): khi hủy cấu trúc thuộc tính kiểu nguyên thủy của đối tượng
reactive
, bạn không còn giữ được liên kết reactivity.
Vì vậy, nên ưu tiên sử dụng ref()
để khai báo trạng thái phản ứng chính cho các ứng dụng Vue.js.
Kết Luận
Trong bài viết này, chúng ta đã tìm hiểu sâu về cơ chế phản ứng của Composition API trong Vue.js. Chúng ta đã thấy lý do tại sao nên sử dụng phản ứng và một vài phương pháp khai báo và sử dụng chúng. Cảm ơn các bạn đã theo dõi!
source: viblo