Component (thành phần) là một khái niệm cốt lõi trong Vue.js, cho phép bạn xây dựng các giao diện người dùng phức tạp bằng cách chia nhỏ chúng thành các phần nhỏ hơn, có thể tái sử dụng và dễ quản lý. Bài viết này sẽ đi sâu vào component trong Vue.js, từ những ví dụ cơ bản đến cách tái sử dụng, tổ chức và truyền dữ liệu giữa các component.
Mục Lục
- 1 Ví dụ cơ bản về Component trong Vue.js
- 2 Tái sử dụng Component: Xây dựng giao diện linh hoạt
- 3 Tổ chức Component: Xây dựng ứng dụng có cấu trúc
- 4 Truyền dữ liệu xuống Component con bằng Prop
- 5 Một phần tử gốc đơn lập: Cấu trúc template hợp lệ
- 6 Gửi thông tin đến đối tượng cha bằng Sự kiện
- 7 Phân phối nội dung với Slot
- 8 Component động: Linh hoạt trong hiển thị
- 9 Kết luận
Ví dụ cơ bản về Component trong Vue.js
Component trong Vue.js là các đối tượng Vue có thể tái sử dụng. Hãy xem xét ví dụ sau:
Ví dụ Component
Trong ví dụ này, <button-counter>
là tên của component. Chúng ta có thể sử dụng component này như một phần tử trong đối tượng Vue gốc:
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: 'Bấm vào tôi {{ count }} lần.'
})
new Vue({
el: '#example'
})
Vì component là các đối tượng Vue tái sử dụng, chúng cũng chấp nhận các tùy chọn như data
, computed
, watch
, methods
và các hook vòng đời. Tuy nhiên, có một vài ngoại lệ, chẳng hạn như tùy chọn el
, chỉ dành cho đối tượng Vue gốc.
Tái sử dụng Component: Xây dựng giao diện linh hoạt
Một trong những lợi ích lớn nhất của component là khả năng tái sử dụng. Bạn có thể sử dụng một component nhiều lần trong ứng dụng của mình:
Mỗi khi bạn sử dụng một component, một đối tượng mới của component đó sẽ được tạo. Điều này có nghĩa là mỗi component sẽ giữ một giá trị count
riêng biệt.
Ví dụ về tái sử dụng component trong Vue.js
Điều quan trọng cần lưu ý là tùy chọn data
của component phải là một hàm. Điều này đảm bảo rằng mỗi đối tượng component có một bản sao riêng biệt của đối tượng data
được trả về:
data: function () {
return {
count: 0
}
}
Nếu data
là một object, tất cả các component sẽ chia sẻ cùng một object, dẫn đến các hành vi không mong muốn.
Tổ chức Component: Xây dựng ứng dụng có cấu trúc
Một ứng dụng Vue.js thường được tổ chức dưới dạng một cây component lồng nhau. Ví dụ, bạn có thể có các component cho header
, sidebar
và content
, mỗi component này lại chứa các component con cho menu
, blog-post
, v.v.
Để có thể sử dụng trong các template, component phải được đăng ký. Có hai cách đăng ký component: toàn cục và cục bộ.
Component đăng ký ở cấp toàn cục có thể được sử dụng trong template của bất kỳ đối tượng Vue gốc (new Vue
) nào được tạo ra sau đó – và trong tất cả các component con trên cây component của đối tượng đó. Ví dụ: Vue.component('button-counter', ...)
đăng ký component button-counter
trên toàn cục.
Truyền dữ liệu xuống Component con bằng Prop
Để component thực sự hữu ích, chúng ta cần có cách để truyền dữ liệu vào chúng. Đó là lúc prop
phát huy tác dụng.
Prop
là các thuộc tính tùy chỉnh mà bạn có thể đăng ký trên một component. Khi một giá trị được truyền vào một prop, nó sẽ trở thành một “prop-erty” của đối tượng component đó. Để truyền tiêu đề (title) vào component blog-post
, chúng ta sử dụng tùy chọn props
:
Vue.component('blog-post', {
props: ['title'],
template: '
{{ title }}
'
})
Một component có thể có bao nhiêu prop tùy ý và prop có thể nhận bất kỳ giá trị gì. Trong template, bạn có thể truy xuất giá trị này trên đối tượng component, giống như với data
.
Sau khi prop đã được đăng ký, bạn có thể truyền dữ liệu vào như một thuộc tính tùy chỉnh:
Trong một ứng dụng điển hình, bạn có thể có một mảng các bài viết trong data
:
data: {
posts: [
{ id: 1, title: 'Giới thiệu về Vue.js', content: '...' },
{ id: 2, title: 'Các khái niệm cơ bản trong Vue.js', content: '...' }
]
}
và sau đó render một component cho mỗi bài viết:
Ở đây, chúng ta sử dụng v-bind
để truyền động prop. Cách làm này đặc biệt hữu ích khi bạn không biết trước được chính xác nội dung bạn sẽ render.
Một phần tử gốc đơn lập: Cấu trúc template hợp lệ
Khi xây dựng component blog-post
, template của bạn có thể chứa nhiều thứ hơn là chỉ mỗi title
. Ít nhất bạn cũng sẽ có thêm nội dung bài viết:
{{ title }}
{{ content }}
Tuy nhiên, nếu bạn sử dụng template này, Vue sẽ thông báo lỗi “Component template should contain exactly one root element” (template của component phải chứa chính xác một phần tử gốc). Bạn có thể sửa lỗi này bằng cách bọc template trong một phần tử cha, ví dụ:
{{ title }}
{{ content }}
Gửi thông tin đến đối tượng cha bằng Sự kiện
Trong nhiều trường hợp, component con cần giao tiếp ngược lên đối tượng cha. Ví dụ, chúng ta muốn thêm tính năng phóng to font chữ của bài viết, nhưng vẫn giữ nguyên các thành phần khác trên trang.
Chúng ta có thể hỗ trợ tính năng này bằng cách thêm thuộc tính postFontSize
trong data
của đối tượng cha:
data: {
postFontSize: 1
}
Thuộc tính này có thể được dùng trong template để quản lý cỡ chữ của tất cả các bài viết:
{{ post.title }}
{{ post.content }}
Bây giờ, hãy thêm một nút để tăng cỡ chữ ngay trước nội dung của mỗi bài viết:
Phóng to
{{ title }}
{{ content }}
Khi nút “Phóng to” được bấm, chúng ta muốn yêu cầu đối tượng cha phóng to cỡ chữ của tất cả các bài viết. Để phát ra (emit) một sự kiện, chúng ta có thể gọi phương thức $emit
cho sẵn và truyền vào tên của sự kiện:
methods: {
enlargeText: function () {
this.$emit('enlarge-text')
}
}
Sau đó, trong component cha, chúng ta có thể lắng nghe sự kiện này bằng v-on
giống như với các sự kiện DOM:
{{ post.title }}
{{ post.content }}
methods: {
onEnlargeText: function (enlargeAmount) {
this.postFontSize += enlargeAmount
}
}
Phân phối nội dung với Slot
Giống như các phần tử HTML, việc có thể truyền nội dung vào một component thường rất hữu ích, ví dụ:
Nội dung ở đây
có thể render thành:
Nội dung ở đây
Việc này rất đơn giản với phần tử tùy biến “ của Vue:
Như bạn thấy, chúng ta chỉ cần thêm “ vào nơi cần thể hiện nội dung.
Component động: Linh hoạt trong hiển thị
Đôi khi, bạn muốn chuyển qua lại giữa các component, ví dụ như trên một giao diện tab:
Tab 1
Tab 2
Ví dụ trên hoạt động nhờ thuộc tính đặc biệt is
của một component trong Vue:
data: {
currentTab: 'tab-1',
tabs: ['tab-1', 'tab-2']
},
components: {
'tab-1': { template: '<div>Nội dung tab 1</div>' },
'tab-2': { template: '<div>Nội dung tab 2</div>' }
}
Trong ví dụ trên, currentTabComponent
có thể chứa:
- Tên của một component đã được đăng ký, hoặc
- Object chứa các tùy chọn của một component
Kết luận
Component là một công cụ mạnh mẽ trong Vue.js, cho phép bạn xây dựng các ứng dụng phức tạp một cách dễ dàng và hiệu quả. Bằng cách hiểu rõ các khái niệm cơ bản về component, bạn có thể tận dụng tối đa sức mạnh của Vue.js để tạo ra các giao diện người dùng tuyệt vời.