协作头脑风暴
brainstorming
在实现前澄清需求、探索设计选择,并形成清晰的开发方向。
harmony-arkts【开发与工程】Best practices for HarmonyOS application development with ArkTS and ArkUI, covering components, state management, resources, layout, lifecycle, and accessibility. Use when writing .ets component files, using ArkUI decorators like @Component/@State/@Prop/@Link, building layouts with Column/Row/Stack/List, managing HarmonyOS app resources with $r(), or…
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
This skill covers building HarmonyOS applications with ArkTS and the declarative ArkUI framework, including component structure, state management, layout, lifecycle, resources, and accessibility.
struct decorated with @Component, named in PascalCase.@State, @Prop, @Link, and other state decorators first, before any methods.aboutToAppear()/aboutToDisappear() (and others as needed) after state, before build().build() last, using ArkUI primitives (Column, Row, Stack, List, etc.) to lay out child components.build() grows large or nested, pull sections into smaller @Component structs or @Builder functions.$r().@Component to define components and PascalCase for the component struct name (e.g., struct UserProfileCard).@State, @Prop, @Link, @StorageLink, plain fields) near the top of the component, before methods and lifecycle hooks.aboutToAppear, aboutToDisappear, onPageShow, onPageHide) before build() so the component's lifecycle is easy to scan.build() last and keep it focused purely on UI composition — pull data transformation and business logic out into methods called from build(), not embedded inline.@Component structs (or @Builder functions for lightweight, reusable UI fragments) once a build() method grows past a screenful or nests more than a few levels deep.@State for state owned and mutated by the component itself.@Prop for one-way parent-to-child data — the child gets its own copy and local changes don't propagate back up.@Link only for intentional two-way binding where the child genuinely needs to mutate the parent's state (e.g., a custom form control).items and itemCount as separate @State fields when itemCount can be this.items.length).AppStorage/LocalStorage used indiscriminately) unless the project has an established app-state pattern; prefer passing data down through props/links for anything not genuinely global.@Component
export struct CounterCard {
@Prop label: string = 'Counter';
@State private count: number = 0;
private maxCount: number = 99;
aboutToAppear(): void {
console.info(`CounterCard mounted with label=${this.label}`);
}
private increment = (): void => {
if (this.count >= this.maxCount) {
return;
}
this.count += 1;
};
private reset = (): void => {
this.count = 0;
};
build() {
Column({ space: 12 }) {
Text(this.label)
.fontSize(18)
.fontWeight(FontWeight.Medium)
Text(`${this.count}`)
.fontSize(32)
.fontColor($r('app.color.primary'))
.accessibilityText(`Current count is ${this.count}`)
Row({ space: 8 }) {
Button('Increment')
.onClick(this.increment)
.accessibilityText('Increment counter')
Button('Reset')
.onClick(this.reset)
.accessibilityText('Reset counter')
}
}
.width('100%')
.padding(16)
.alignItems(HorizontalAlign.Center)
}
}
Column, Row, Stack, List, and other ArkUI layout primitives intentionally based on the axis and stacking behavior actually needed, rather than defaulting to Stack and positioning everything absolutely.layoutWeight) — before visual properties (color, font, border) in the chained modifier calls, so structure reads before decoration..margin({ top: 8, bottom: 16, left: 12, right: 12 })) rather than a single shorthand that implies uniform spacing.vp) consistently for sizes so layouts scale correctly across device pixel densities; avoid mixing raw pixel values.'100%', '50%') for sizes that should be relative to the parent container instead of hardcoded fixed values.$r('app.color.primary'), $r('app.float.spacing_md')) when the project supports it, instead of repeating literals across components..onClick(() => this.handleTap()) or a bound class field like private handleTap = () => {...}) so this binds correctly without extra boilerplate.try/catch around await) and surface user-facing errors (a toast, an inline error state) instead of letting a rejected promise disappear silently.aboutToAppear, aboutToDisappear, onPageShow, onPageHide, onBackPress) only for setup/teardown that genuinely depends on the component or page's lifecycle — don't use them as a dumping ground for logic that could live in a regular method.$r() to reference app resources (strings, colors, media, floats) instead of embedding literal values directly in component code.resources/base/element/string.json, color.json, float.json by feature or screen so they stay navigable as the app grows..accessibilityText(), .accessibilityDescription()) and correct focus handling (.focusable(true), .tabIndex()) for every interactive element.build() instead of in dedicated methods — build() should read like a UI tree, not a program.@Link two-way binding when a simple one-way @Prop would do, which makes data flow harder to trace and invites accidental mutation from child components.console.log/console.info calls in production code paths, which adds noise and can leak internal state into logs.