Components trong Vue.js – từ cách khai báo props, sử dụng v-model
, emit sự kiện, đến slot, provide/inject và composables.
Khám phá cách xây dựng và sử dụng components hiệu quả trong Vue 3: props, slots, v-model, emit, provide/inject và hơn thế nữa.
Components trong Vue.js là gì?
Component (thành phần) là trái tim của mọi ứng dụng Vue.js. Nó là một khối giao diện tái sử dụng được, gồm:
- Template: Giao diện HTML.
- Script/Logic: Xử lý dữ liệu, tương tác người dùng.
- Style: CSS để định dạng thành phần.
Nhờ cấu trúc này, Vue cho phép bạn chia nhỏ giao diện thành các block riêng biệt (component-based architecture), giúp:
- Tái sử dụng code nhiều lần.
- Tách biệt logic và giao diện từng phần.
- Dễ kiểm thử và mở rộng.
Props – Truyền dữ liệu vào component
Khai báo Props cơ bản
Props (properties) là cách để cha truyền dữ liệu sang component con. Trong Vue 3 với <script setup>
, bạn khai báo như sau:
<script setup>
defineProps(['title', 'count']);
</script>
Bạn có thể sử dụng title
và count
trong template như biến bình thường.
Khai báo Props có kiểu dữ liệu
Để đảm bảo an toàn, bạn nên định nghĩa props với kiểu rõ ràng bằng TypeScript:
<script setup lang="ts">
const props = defineProps<{
title: string;
count?: number; // Có thể có hoặc không
}>();
</script>
Prop tĩnh và động
Trong component cha, bạn có thể truyền props theo hai cách:
<!-- Truyền prop tĩnh (dạng chuỗi) -->
<MyComponent title="Tĩnh" />
<!-- Truyền prop động (biến từ script) -->
<MyComponent :title="dynamicTitle" />
Dấu :
giúp Vue biết đây là một biểu thức JavaScript, không phải chuỗi thuần.
Component Events – Giao tiếp từ con → cha
Để gửi dữ liệu từ con lên cha, bạn dùng emit events.
Component cha:
<MyComponent @custom-event="handleEvent" />
Component con:
<script setup>
const emit = defineEmits(['custom-event']);
emit('custom-event', data);
</script>
Bạn có thể định nghĩa nhiều sự kiện với defineEmits
.
Đăng ký Component toàn cục
Nếu muốn dùng component ở bất kỳ đâu trong app, bạn cần đăng ký toàn cục:
// main.ts hoặc main.js
import { createApp } from 'vue';
import App from './App.vue';
import MyComponent from './components/MyComponent.vue';
const app = createApp(App);
app.component('MyComponent', MyComponent);
Component với v-model
Cơ bản
<MyInput v-model="name" />
Trong component con, bạn cần khai báo:
<script setup>
const name = defineModel();
</script>
Vue sẽ tự hiểu modelValue
là prop và tạo sự kiện update:modelValue
.
Dùng đối số với v-model
Vue 3 hỗ trợ v-model
có tên tuỳ chỉnh:
<MyInput v-model:title="header" />
Trong component con:
const title = defineModel('title');
Xử lý Modifiers trong v-model
Vue chưa hỗ trợ modifier (như .trim
, .number
) trực tiếp với component, nhưng bạn có thể truyền modelModifiers
và xử lý thủ công:
const modelModifiers = defineModel().modifiers;
// Kiểm tra: modelModifiers.trim === true
Slot – Truyền nội dung động vào component
Slot giúp component cha chèn nội dung vào component con:
<CustomCard>
<template #header>
<h1>Tiêu đề</h1>
</template>
<p>Nội dung chính</p>
</CustomCard>
Trong component CustomCard.vue
:
<template>
<header><slot name="header" /></header>
<main><slot /></main>
</template>
Slot rất mạnh khi bạn muốn làm component linh hoạt, chẳng hạn như modal, card, form wrapper…
Provide và Inject – Chia sẻ dữ liệu không qua prop
Nếu bạn có dữ liệu muốn chia sẻ giữa các component cha và cháu mà không muốn truyền props qua nhiều cấp, hãy dùng provide
và inject
.
Component cha:
import { provide, ref } from 'vue';
const theme = ref('dark');
provide('theme', theme);
Component con hoặc cháu:
import { inject } from 'vue';
const theme = inject('theme'); // theme là ref, có thể dùng reactivity
Cập nhật state:
Vì theme
là một ref
, component cháu có thể theo dõi hoặc cập nhật trực tiếp, giữ tính đồng bộ.
Async Component – Tải component khi cần
Để cải thiện hiệu năng, bạn có thể tải component khi cần dùng:
import { defineAsyncComponent } from 'vue';
const AsyncComp = defineAsyncComponent(() => import('./MyComponent.vue'));
Hữu ích trong:
- Lazy loading route
- Giảm kích thước bundle
- Tối ưu FCP (First Contentful Paint)
Composables – Tái sử dụng logic với Composition API
Composable là hàm tái sử dụng logic trong Vue 3. Ví dụ:
export function useCounter() {
const count = ref(0);
const increment = () => count.value++;
return { count, increment };
}
Trong component:
const { count, increment } = useCounter();
Composables giúp:
- Tách biệt logic khỏi UI.
- Tái sử dụng code giữa nhiều component.
- Dễ kiểm thử và mở rộng hệ thống.
Tổng kết
Tính năng | Mục đích |
---|---|
Component | Xây dựng UI theo khối |
Props | Truyền dữ liệu từ cha sang con |
Emit Events | Giao tiếp từ con về cha |
Slots | Chèn nội dung động vào component |
v-model trong component | Giao tiếp 2 chiều dữ liệu |
Provide & Inject | Chia sẻ dữ liệu toàn cục theo hierarchy |
Async Component | Cải thiện hiệu năng bằng lazy load |
Composables | Tái sử dụng logic business |
Vue.js giúp việc phát triển UI trở nên linh hoạt, sạch sẽ và mở rộng được nhờ kiến trúc component. Việc nắm rõ cách hoạt động và các kỹ thuật nâng cao sẽ giúp bạn xây dựng ứng dụng hiệu quả, dễ bảo trì và chuyên nghiệp hơn.