> For AI agents: the complete documentation index is available at https://nhanbe.id.vn/llms.txt, the full documentation bundle is available at https://nhanbe.id.vn/llms-full.txt.

# Components Basics

Component là instance Vue tái sử dụng, có template, logic và style riêng. Trong AEM, mỗi AEM component thường mount một root Vue component, root đó chia nhỏ thành các child component thuần frontend.

## Định nghĩa component

Component nhận gần như mọi option của instance (`data`, `computed`, `methods`, `watch`, lifecycle hooks), trừ vài option chỉ dành cho root như `el`.

```js
Vue.component('button-counter', {
  data() {
    return { count: 0 }
  },
  template: '<button @click="count++">Clicked {{ count }} times</button>'
})
```

Trong dự án thực tế dùng Single File Component (`.vue`) thay cho template string:

```vue
<template>
  <button @click="count++">Clicked {{ count }} times</button>
</template>

<script>
export default {
  name: 'ButtonCounter',
  data() {
    return { count: 0 }
  }
}
</script>
```

## data của component phải là function

Component dùng lại nhiều lần. Nếu `data` là object dùng chung, mọi instance sẽ share cùng state. `data` phải là function trả về object mới để mỗi instance có state độc lập.

```js
// ĐÚNG: mỗi instance một object riêng
data() {
  return { count: 0 }
}

// SAI: mọi instance share chung
data: { count: 0 }
```

## Tái sử dụng và tổ chức cây component

Mỗi lần dùng component là một instance độc lập:

```html
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
```

Ứng dụng tổ chức thành cây: root chứa các component con, con lại chứa con của nó.

```mermaid
graph TD
  Root["Root component (mount point)"] --> Header
  Root --> Content
  Content --> Card1["ProductCard"]
  Content --> Card2["ProductCard"]
  Root --> Footer
```

## Luồng dữ liệu một chiều

Cha truyền xuống con qua **props**. Con báo ngược lên cha qua **events**. Con không sửa trực tiếp dữ liệu của cha.

```mermaid
graph LR
  Parent -- props (xuống) --> Child
  Child -- events (lên) --> Parent
```

Chi tiết ở các note Props và Custom Events.

## name option

`name` giúp ích cho debug (hiện trong Vue Devtools), cho phép component tự gọi đệ quy, và dùng với `<keep-alive>`. Luôn đặt `name` cho SFC.

## Tips cho AEM

Root component mount vào DOM HTL render. Các child component nằm gọn trong cây Vue, AEM không cần biết tới chúng.

```js
import Vue from 'vue'
import ProductList from './components/ProductList.vue'

const el = document.getElementById('product-list')
if (el) {
  new Vue({
    render: h => h(ProductList, {
      props: { items: JSON.parse(el.dataset.items || '[]') }
    })
  }).$mount(el)
}
```

`ProductList` bên trong tự render nhiều `ProductCard` mà không cần thêm mount point hay dialog riêng. Chỉ tạo AEM component riêng khi author cần cấu hình độc lập.
