原因:@State 只能观测到第一层属性变化,嵌套属性修改不会触发刷新。
// ❌ 错误:直接修改嵌套属性
@State order: Order = new Order()
this.order.items[0].quantity = 2 // UI 不会更新
// ✅ 修复方式一:整体赋值(触发@State观测)
this.order = { ...this.order, items: [...this.order.items] }
// ✅ 修复方式二(推荐,API 12+):使用 @ObservedV2 + @Trace
@ObservedV2
class Order {
@Trace items: OrderItem[] = []
}
this.order.items[0].quantity = 2 // UI 正常更新原因:keyGenerator 不唯一或不稳定。
// ❌ 错误:使用 index 作为 key
ForEach(this.list, (item) => { ... }, (item, index) => index.toString())
// ✅ 正确:使用业务唯一标识
ForEach(this.list, (item) => { ... }, (item) => item.id.toString())// ❌ 误用 @Prop 期望双向同步
@Component struct Child {
@Prop count: number = 0 // 单向传递
}
// ✅ 需要双向同步时使用 @Link
@Component struct Child {
@Link count: number // 双向同步
}
// 父组件传递:Child({ count: $count })// ❌ 错误:dialogController 不释放
dialogController: CustomDialogController = new CustomDialogController({ ... })
// ✅ 正确:在 aboutToDisappear 中释放
aboutToDisappear() {
this.dialogController = undefined // 释放控制器
}// ❌ 错误:请求后不销毁
const httpRequest = http.createHttp()
httpRequest.request(url, options)
// ✅ 正确:在 finally 中销毁
try {
const response = await httpRequest.request(url, options)
// 处理响应
} finally {
httpRequest.destroy()
}// ❌ 错误:在 aboutToAppear 中使用 router.getParams() 可能返回 null
aboutToAppear() {
const params = router.getParams() // 可能为null
}
// ✅ 正确:添加空值检查
aboutToAppear() {
const params = router.getParams() as Record<string, Object> | null
if (params) {
this.id = params['id'] as string
}
}// ❌ 错误:@Builder 按引用传递时参数变化不触发UI刷新
@Builder ItemBuilder(item: Item) {
Text(item.name) // item是按值传递,修改item不会刷新
}
// ✅ 正确:使用 @Builder 按引用传递
@Builder ItemBuilder($: { item: Item }) {
Text($.item.name) // 按引用传递,变化会刷新
}// 大数据列表使用 LazyForEach 而不是 ForEach
class MyDataSource implements IDataSource {
// ...实现 IDataSource 接口
}
List() {
LazyForEach(this.dataSource, (item) => {
ListItem() { this.ItemBuilder(item) }
}, (item) => item.id.toString())
}
// 条件渲染避免渲染不可见的内容
if (this.isVisible) {
ComplexComponent()
}
// 而不是
ComplexComponent().visibility(this.isVisible ? Visibility.Visible : Visibility.None)// ❌ 过多独立状态变量
@State name: string = ''
@State age: number = 0
@State gender: string = ''
@State address: string = ''
// ✅ 合并为对象(减少观测开销)
@State userInfo: UserInfo = { name: '', age: 0, gender: '', address: '' }// ❌ 大范围状态变更触发整页刷新
@State pageData: PageData = { ... }
// ✅ 将频繁变化的状态放在独立组件中
@Component
struct PriceDisplay {
@Prop price: number = 0 // 只刷新价格区域
build() { Text(`¥${this.price}`) }
}// ❌ 每次渲染创建新对象
ForEach(this.items, (item) => {
ListItem() {
Row({ space: 10 }) { ... } // 每次创建新Row
}
})
// ✅ 使用 @Builder 复用UI结构
@Builder ItemBuilder(item: Item) {
Row({ space: 10 }) { ... }
}// 使用合适的图片解码尺寸
Image(url)
.objectFit(ImageFit.Cover)
.interpolation(ImageInterpolation.Low) // 小图不需要高插值
// 缓存图片
.autoResize(true)
.syncLoad(false) // 异步加载避免阻塞类和对象必须先声明再使用
,ArkTS 不支持声明提升
使用 as 类型断言需谨慎
,ArkTS 对类型检查更严格
不要使用 any 类型
,使用具体类型或泛型
枚举仅支持数字枚举
空安全
:明确区分 null / undefined / 初始值
$ 双绑语法仅用于特定场景
:TextInput、Toggle、Slider 等
@Builder 函数的参数传递方式
:
按值传递:@Builder func(param: Type) — 不追踪变化
按引用传递:@Builder func($: { param: Type }) — 追踪变化
每次请求后是否在 finally 中调用 destroy()