HarmonyOS 鸿蒙 ArkUI 保留属性名踩坑实录 —— 那些「看起来能命名、一编译就报错」的 @Prop

📅 2026/8/19 22:53:17
HarmonyOS 鸿蒙 ArkUI 保留属性名踩坑实录 —— 那些「看起来能命名、一编译就报错」的 @Prop
一、现象同一个坑项目里踩了五次这个项目做了十几个组件但「保留属性名冲突」这个坑在至少五个地方留下了注释痕迹// FlowAvatar.ets /** Logical pixel size. Named avatarSize because size is an ArkUI attribute. */ Prop avatarSize: number 64; /** Depth shadow. Named showShadow because shadow is an ArkUI attribute. */ Prop showShadow: boolean true; // ThinkingOrb.ets /** Logical preset size. Named orbSize because size is an ArkUI attribute. */ Prop orbSize: ThinkingOrbSize ThinkingOrbSize.Avatar; // BorderBeam.ets /** Corner radius in vp. Named beamRadius because borderRadius is an ArkUI attribute. */ Prop beamRadius: number -1; /** Glow brightness multiplier. Named beamBrightness because brightness is an ArkUI attribute. */ Prop beamBrightness: number -1;还有 GrokBot 的botSize不用size、SlotText 的rollDirection不用direction。关键问题来了为什么「给Prop起名size」会报错这背后是 ArkUI 一个非常具体的机制搞清楚它你就再也不会踩。二、根因Prop名字和组件属性是同名冲突2.1 机制在 ArkUI 里Component的Prop成员本质上会变成这个组件的构造参数 / 属性。而当你在build()里这样写build() { Column() .size({ width: 100, height: 100 }) // ← 通用属性 size }ArkUI 的「通用属性」size是全局保留的 attribute 名。如果你的组件同时声明了Prop size: number 64;就会产生命名冲突——编译器无法区分「这个size是我的Prop还是 ArkUI 内置的属性」。2.2 为什么有时候「不报错但错乱」更危险的是部分情况不报错但语义错乱。比如shadow、direction、borderRadius这些如果只在特定上下文里冲突编译器可能不会立刻拒绝但你的「自定义Prop shadow」会和「通用阴影属性」混在一起导致传参不生效、或者样式被意外覆盖。这就是为什么「保留属性名」是比「保留关键字」更隐蔽的坑——它不一定报错可能只是让你的组件行为悄悄变错。三、高危保留名清单基于项目里实际踩过的 ArkUI 通用属性整理一份「起名要避开的高危名单」想表达的含义❌ 高危名✅ 项目里的替代尺寸sizeavatarSize/orbSize/botSize阴影shadowshowShadow方向directionrollDirection/axis圆角borderRadiusbeamRadius/cornerRadius亮度brightnessbeamBrightness/glow透明度opacitydim/alpha缩放scalevisualScale/zoom模糊blursideBlur/blurRadius通用规律所有ArkUI 通用属性size、opacity、scale、rotate、blur、shadow、borderRadius、backgroundColor、padding、margin……以及布局方向属性direction、align都不该拿来给Prop命名。四、为什么「加个前缀」就够了项目里所有的替代名都遵循同一个规律加一个「语义前缀」把「通用词」变成「专有词」。原意前缀法sizeavatarSize、orbSize、botSize、cellSizeshadowshowShadowradiusbeamRadius、cardRadius、cellRadiusbrightnessbeamBrightness前缀的作用是消除二义性avatarSize明确是「这个头像组件的尺寸」不会和size通用属性混淆。但注意前缀不能是随意的要表达「这个组件特有的语义」。avatarSize读起来是「头像的尺寸」orbSize是「状态球的尺寸」botSize是「机器人尺寸」——每个都落在「组件自身」的语义里而不是泛泛的size。五、一个容易忽略的「边界 case」label项目里 GrokBot 和 GradientSpin 都用了Prop label// GrokBot.ets Prop label: string GrokBot; // GradientSpin.ets Prop label: string Loading;label严格来说也是 ArkUI 的通用属性Text、Button等都有label。但这里它们没踩坑原因是这些Prop label是自定义组件的成员不是直接作为 ArkUI 内置属性的替代组件内部是用.accessibilityText(this.label)把值消费掉而不是Prop label和内置label在同一层冲突。这提醒我们「保留名」的判断要结合「具体冲突场景」。label在这些组件里之所以安全是因为它没有被用来「和内置 label 抢同一个语义槽」。但如果你在build()里同时写.label(this.label)和声明Prop label就要小心了——能避开就避开用accessibilityLabel或title更稳妥SlotText 就用了accessibilityLabel。六、落地成一条命名纪律把坑沉淀成习惯三条就够Prop名字永远别和 ArkUI 通用属性撞——起名前列一下「我要表达的概念」是否在size/opacity/scale/rotate/blur/shadow/direction/borderRadius/...这个清单里。撞了就加「组件语义前缀」——avatarSize、orbSize、beamRadius而不是mySize、size2这种无意义前缀。注释里写明白「为什么叫这个名」——项目里每个改名的Prop上面都留了Named X because Y is an ArkUI attribute这不是多余而是给下一个维护者和未来的自己的提示避免有人「好心」把它改回size又踩一遍。七、总结「保留属性名」这个坑单独看很小但它有三个讨厌的特质高频几乎每个自定义组件都会碰到「尺寸/阴影/方向/圆角」这些概念。隐蔽不一定报错可能只是行为悄悄错乱。会复发这次记住了size下次换个组件又踩direction。所以它值得被单独拎出来写一篇——不是因为它复杂而是因为它最好的解法是一份「起名 blacklist」 一个「加前缀」的习惯提前防住而不是每次报错了再改。Prop别叫size——叫avatarSize或orbSize。撞了 ArkUI 通用属性加组件语义前缀。改了名就留注释别让下一个人改回去再踩一遍。这一篇加上前面的《分层范式》《DisplaySync》《移植方法论》三篇组成了 ArkUILab 项目在鸿蒙自定义组件开发上的完整横切方法论怎么分层、怎么驱动帧、怎么移植、怎么命名。四篇合起来就是一个「从零写一个可复用、可测试、可移植的鸿蒙动效组件」的完整地图。