Giới thiệu
Trong Vue 3, việc áp dụng destructuring (phân rã) để truy cập vào các thuộc tính của props object trong các component con đã trở thành một phương pháp phổ biến và tiện lợi cho lập trình viên. Tuy nhiên, một vấn đề quan trọng liên quan đến tính phản ứng (reactivity) có thể xảy ra khi sử dụng kỹ thuật này. Trong bài viết hôm nay, chúng ta sẽ khám phá sâu về vấn đề này thông qua một ví dụ cụ thể và đề xuất các giải pháp hiệu quả khi sử dụng destructuring cho props object trong Vue 3.
Mối Quan Hệ Giữa Destructuring và Tính Phản Ứng trong Props
Khi destructuring props object để truy cập các thuộc tính bên trong component con, một vấn đề liên quan đến tính phản ứng có thể hình thành. Cụ thể, khi props được destructured, các thuộc tính này trở thành các biến nguyên thuần trong phạm vi của component con, dẫn đến việc mất đi khả năng tự động cập nhật mà Vue cung cấp.
Điều này đồng nghĩa với việc các thay đổi trong dữ liệu của component cha sẽ không được phản ánh ngay lập tức trong component con, gây ra những lỗi khó hiểu trong quá trình phát triển.
Ví Dụ Cụ Thể Về Vấn Đề Tính Phản Ứng Khi Destructuring Props
Xem xét một tình huống trong đó một component cha (Parent) chứa một thuộc tính dữ liệu message, và component con (Child) nhận thuộc tính message này thông qua props. Chúng ta dự định khi giá trị message trong component cha thay đổi, component con cũng sẽ tự động cập nhật để hiển thị giá trị mới. Dưới đây là ví dụ mã nguồn:
html
<!-- Parent.vue -->
<template>
<div>
<Child :message="message" />
<button @click="updateMessage">Cập Nhật Thông Điệp</button>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello, Vue 3!',
};
},
methods: {
updateMessage() {
this.message = 'Thông Điệp Đã Cập Nhật';
},
},
};
</script>
<!-- Child.vue -->
<template>
<div>
<p>{{ propMessage }}</p>
</div>
</template>
<script>
export default {
props: {
message: String,
},
mounted() {
const { message } = this; // Destructuring props object
console.log(message); // Hiển thị giá trị hiện tại của message trong component con
},
computed: {
propMessage() {
return this.message;
},
},
};
</script>
Trong ví dụ trên, khi người dùng nhấn nút "Cập Nhật Thông Điệp", chúng ta mong đợi rằng thông điệp trong component con cũng sẽ được cập nhật. Tuy nhiên, vì sử dụng destructuring, giá trị message trong component con sẽ không thay đổi và console sẽ không hiển thị thông báo mới nào.
Giải Pháp Cho Vấn Đề Tính Phản Ứng
Để giải quyết vấn đề về tính phản ứng khi sử dụng destructuring cho props object, việc đơn giản nhất là truy cập trực tiếp vào thuộc tính của props thay vì destructuring. Dưới đây là mã nguồn đã được điều chỉnh:
html
<!-- Child.vue -->
<template>
<div>
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
props: {
message: String,
},
mounted() {
const message = this.message; // Không sử dụng destructuring
console.log(message); // Hiển thị giá trị hiện tại của message trong component con
},
computed: {
propMessage() {
return this.message;
},
},
};
</script>
Bằng cách truy cập trực tiếp vào props object, chúng ta đảm bảo rằng tính năng reactive của Vue 3 vẫn hoạt động bình thường. Khi giá trị message trong component cha thay đổi, component con sẽ hiển thị giá trị mới ngay lập tức.
Nếu người dùng vẫn muốn sử dụng destructuring mà không làm mất đi tính reactive, chúng ta có thể sử dụng hàm toRef
trong Vue 3. Xem ví dụ dưới đây:
html
<!-- Child.vue -->
<template>
<div>
<p>{{ propMessage }}</p>
</div>
</template>
<script>
import { toRef } from 'vue';
export default {
props: {
message: String,
},
setup(props) {
const propMessage = toRef(props, 'message');
return {
propMessage
};
},
};
</script>
Trong ví dụ này, chúng ta sử dụng toRef(props, 'message')
để tạo một ref object cho biến propMessage từ thuộc tính message của props. Điều này giữ cho propMessage liên kết với giá trị của props và đảm bảo rằng khi message thay đổi, propMessage cũng sẽ được cập nhật tự động.
Sử dụng toRef
là một cách hiệu quả để kết hợp lợi ích của destructuring với sự phản ứng tự động của Vue 3, từ đó giúp các lập trình viên dễ dàng hơn trong việc quản lý và phản ứng với các thay đổi dữ liệu trong ứng dụng của họ.
source: viblo