返回 Skill 列表
extension
分类: 开发与工程无需 API Key

"view-composition"

视图组合:@ViewBuilder属性,部分提取,将主体作为目录,命名约定。在实现与视图组合相关的UI模式时使用。

person作者: jakexiaohubgithub

View Composition Rules

@ViewBuilder Computed Properties

Every meaningful section of a view should be a @ViewBuilder computed property:

struct TaskListView: View {
    var body: some View {
        NavigationStack {
            VStack {
                headerView
                taskList
                addButton
            }
        }
    }

    private var headerView: some View {
        Text("My Tasks")
            .font(AppTheme.Fonts.largeTitle)
            .padding()
    }

    private var taskList: some View {
        List(tasks) { task in
            TaskRow(task: task)
        }
    }

    private var addButton: some View {
        Button("Add Task") {
            showAddSheet = true
        }
        .buttonStyle(.borderedProminent)
    }
}

Size Guidelines

  • Each computed property: 15-40 lines
  • If a section exceeds 40 lines, extract it to a separate struct
  • If a section is reused in multiple views, extract to a separate file

Section Naming Pattern

Use descriptive suffixes:

  • headerSection, headerView — top area
  • contentSection, contentView — main content
  • footerSection — bottom area
  • {feature}Section — feature-specific (e.g., profileSection, statsSection)
  • {action}Button — action buttons (e.g., addButton, saveButton)

When to Extract to Separate Struct

Extract a section into its own View struct when:

  1. It exceeds 40 lines of code
  2. It's reused across multiple views
  3. It has its own state (needs @State or @Binding)
  4. It represents a distinct UI component (e.g., a card, a row)

Body Should Only Contain Property References

The body property should be a composition of computed properties — not raw implementation:

// Good — body is a clear outline
var body: some View {
    ScrollView {
        headerSection
        featureCards
        recentActivity
    }
}

// Bad — body contains raw implementation
var body: some View {
    ScrollView {
        VStack(alignment: .leading) {
            Text("Welcome")
                .font(AppTheme.Fonts.largeTitle)
            // ... 50 more lines
        }
    }
}