Bỏ qua để đến nội dung

View, Component & Screen

Chương trước, ta đã xây dựng View Primitives — những View đơn giản, không biết về feature nào dùng nó. Chương này nâng cấp thêm: phân loại View thành 3 loại và hiểu cách kết nối chúng với business logic.

Là View đơn giản, ít hoặc không có logic:

  • Label, Button, Image, Avatar
  • Không biết về feature nào đang dùng nó
  • Có thể sống trong shared UI library

Là View “thông minh hơn” — có state và/hoặc binding:

  • Navigation bar, Date picker, Color picker, SelectionView
  • Quản lý internal state (ví dụ: item nào đang selected)
  • Vẫn không biết về feature cụ thể → cũng có thể sống trong UI library

Ví dụ: SelectionView — hiển thị list, track selected items, handle tap events. Phức tạp hơn một Button, nên phân loại là View Component.

Là View gắn liền với business logic:

  • CourseView — hiển thị toàn bộ màn hình khóa học
  • Biết về data model (Course, Tutor)
  • Không reusable cho feature khác — và điều đó OK
UI Library │ Feature-specific
─────────────────────┼──────────────────
View Primitives │
View Components │ Feature Views
│ (CourseView)

Không phải View Component nào cũng cần sống trong shared UI library. Một số chỉ phục vụ một feature:

Ví dụ: ScheduleView (hiển thị lịch 1-on-1 sắp tới) chỉ dùng trong Course feature. Ta đặt nó trong folder của feature, nhưng vẫn giữ nó self-contained — không depend vào Course model.

Lợi ích: Nếu sau này feature khác cần View này, chỉ cần move nó sang UI library — không cần sửa code.

Feature View là nơi UI meets business logic. Có nhiều cách kết nối:

struct CourseView: View {
let course: Course
var body: some View {
ThumbDescriptionView(
title: course.tutor.name,
description: course.tutor.handle
)
}
}

Khi cần transform data phức tạp hoặc combine nhiều data source:

class CourseViewModel: ObservableObject {
@Published var tutorName: String = ""
@Published var schedule: [Event] = []
func loadCourse() async { ... }
}

Dùng ViewModel khi:

  • Cần transform data phức tạp trước khi display
  • Cần lifecycle management — đặc biệt trên Android (ViewModel survive configuration changes)
  • Nhiều View share cùng state

Không cần ViewModel khi:

  • Data đơn giản, truyền thẳng vào View là đủ
  • Thêm ViewModel chỉ tăng complexity mà không có benefit

4. “Screen” không phải lúc nào cũng full-screen

Phần tiêu đề “4. “Screen” không phải lúc nào cũng full-screen”

Trong daily discussion, ta gọi full-screen view là “screen”. Nhưng kỹ thuật:

  • Trên phone, CourseView chiếm cả screen.
  • Trên tablet, CourseView có thể chỉ chiếm một nửa — nửa còn lại là View khác.
  • Một “screen” trên phone có thể là small component trên tablet.

Takeaway: Khi discuss design, dùng từ “screen” là OK. Nhưng khi code, hãy nghĩ theo feature — không quan trọng View chiếm bao nhiêu pixel.


Kết luận: Phân loại View thành 3 loại (Primitives, Components, Feature Views) giúp bạn biết View nào nên ở đâu, cần bao nhiêu logic, và liệu có reusable không.