Một component to làm hết mọi việc thì khó bảo trì. Cách chia là tách từng mảnh thành component nhỏ tái dùng được — mỗi thẻ thành viên là một TheCard riêng. Nhưng component con lấy dữ liệu từ đâu? Nó không tự gọi ORM; nó nhận từ cha qua props. Bài này tách một thẻ ra component con, cho cha truyền dữ liệu xuống, và chỉ ra quy tắc quan trọng: props chảy một chiều.

Component con nhận, component cha truyền

Con khai static props để khai báo và kiểm những gì nó nhận; cha đăng ký con rồi truyền dữ liệu qua thuộc tính trong template:

Ảnh chụp đoạn mã nền tối ba phần. Phần một component con class TheCard extends Component với static template quan_ca_phe.TheCard và static props gồm card kiểu Object bắt buộc chú thích OWL tự kiểm và dòng tenNgan type String optional true tuỳ chọn, chú thích đọc trong template props card name props card diem. Phần hai template con t-name quan_ca_phe.TheCard div t-att-class props card hang_the bằng vang thì border-warning, div t-esc props card name, div t-esc props card diem cộng chuỗi điểm. Phần ba component cha class QuanDashboard static components gồm TheCard chú thích cho phép dùng thẻ TheCard, và trong template cha TheCard t-foreach state cards t-as card t-key card id card bằng card chú thích truyền card cho mỗi thẻ

Hình 1: Con TheCard khai static props = { card: Object } — vừa là tài liệu (nó cần gì) vừa là kiểm tra: truyền sai kiểu hay thiếu prop bắt buộc, OWL báo lỗi ngay. Con đọc dữ liệu qua this.props.card. Cha QuanDashboard khai static components = { TheCard } để được phép dùng <TheCard/>, rồi trong template truyền card="card" cho mỗi phần tử của t-foreach.

Kết quả: bốn thẻ, mỗi thẻ một component

Mỗi vòng t-foreach dựng một TheCard, nhận card của riêng nó:

Ảnh chụp dashboard OWL thật, trên là ba thẻ số tổng hợp 4 tổng thẻ 385 điểm 1 Vàng, dưới là mục Từng thẻ component con với bốn thẻ nhỏ cạnh nhau: VIP-0001 Hạng bac 150 điểm, VIP-0003 Hạng vang 150 điểm có viền vàng, VIP-0002 Hạng bac 85 điểm, VIP-0004 Hạng bac 0 điểm; mỗi thẻ nhỏ là một component con TheCard

Hình 2: Mục "Từng thẻ (component con)" gồm bốn TheCard, mỗi cái là một instance component riêng nhận props.card khác nhau. Thẻ VIP-0003 (Vàng) có viền vàng nhờ t-att-class xét props.card.hang_the. Con hoàn toàn không biết gì về ORM hay về ba thẻ kia — nó chỉ biết cái card cha đưa cho. Đây là cách tái dùng: viết TheCard một lần, cha dựng bao nhiêu cái tuỳ ý. Chụp bằng trình duyệt thật, không lỗi Console.

Props chảy một chiều

Đây là quy tắc dễ vi phạm nhất. Dữ liệu đi từ cha xuống con, và con không được sửa props:

Ảnh sơ đồ trên nền kem tiêu đề props dữ liệu chảy một chiều từ cha xuống con. Hộp trái CHA QuanDashboard có state cards truyền card bằng card. Ở giữa mũi tên xanh props dữ liệu chỉ sang phải và mũi tên nâu callback onXxx sự kiện chỉ ngược về trái. Hộp phải CON TheCard đọc props card KHÔNG sửa props. Dưới ghi chú một chiều con chỉ đọc props không được gán props card x bằng gì OWL báo lỗi, muốn báo ngược lên cha khi người dùng bấm cha truyền xuống một hàm callback qua props ví dụ onSelect con gọi props onSelect, nhờ vậy dữ liệu luôn có một nguồn duy nhất ở cha dễ lần theo

Hình 3: Props là một chiều. Con chỉ đọc props.card; gán props.card.x = ... là sai — OWL cảnh báo. Nếu con cần "báo lên" cha (người dùng bấm chọn một thẻ), cha truyền xuống một hàm callback qua props (ví dụ onSelect), và con gọi props.onSelect(...). Nhờ nguyên tắc này, mỗi mẩu dữ liệu chỉ có một nguồn duy nhất (ở cha) — khi có bug, bạn biết chính xác chỗ để sửa.

Vài lưu ý khi dùng props

  • Khai static props cho mọi component nhận dữ liệu. Nó là hợp đồng: OWL kiểm kiểu và bắt lỗi sớm. Prop tuỳ chọn thì { type: String, optional: true }.
  • static components = { Con } là bắt buộc để dùng <Con/> trong template — thiếu nó, OWL không biết <Con/> là gì.
  • Truyền hàm để giao tiếp ngược. Không có "emit event" như Vue; quy ước là cha truyền onXxx xuống, con gọi. Đặt tên bắt đầu bằng on cho rõ.
  • Đừng nhét cả this.state của cha làm prop rồi để con sửa. Nếu con cần thay đổi, gọi callback để cha sửa state của mình — giữ một chiều.

Ba ý mang về

  1. Component con nhận dữ liệu qua props: khai static props = { card: Object } (kiểm kiểu), đọc bằng this.props.card; cha khai static components = { TheCard } và truyền card="card".
  2. Props chảy một chiều cha → con: con chỉ đọc, không sửa props; muốn báo ngược thì cha truyền hàm callback (onXxx), con gọi.
  3. Tách component để tái dùng: viết TheCard một lần, cha dựng bao nhiêu instance tuỳ ý qua t-foreach; mỗi mẩu dữ liệu có một nguồn duy nhất ở cha.

Con nhận props và tự vẽ. Nhưng có những việc component cần làm đúng lúc — nạp dữ liệu trước khi hiện, hay chạm vào DOM sau khi đã vẽ. Phần sau đi vào hooks vòng đời: onWillStart, onMounted — chạy code đúng thời điểm trong đời một component.