Components trong Vue.js – Giao diện hiện đại

4 min read

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 titlecount 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-modeltê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 provideinject.

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:

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ăngMục đích
ComponentXây dựng UI theo khối
PropsTruyền dữ liệu từ cha sang con
Emit EventsGiao tiếp từ con về cha
SlotsChèn nội dung động vào component
v-model trong componentGiao tiếp 2 chiều dữ liệu
Provide & InjectChia sẻ dữ liệu toàn cục theo hierarchy
Async ComponentCải thiện hiệu năng bằng lazy load
ComposablesTá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.

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *