本文记录把react-native-star-rating-widget星级评分 / 评分展示适配到 HarmonyOS 的完整过程。它做的事用 SVG 画星星react-native-svg的PathLinearGradient支持整星/半星/四分之一星、PanResponder拖动评分、Animated点击缩放动画另外提供一个只读的StarRatingDisplay。结论可用而且这是又一次零 FAIL—— 14 条判据全 PASS。预检的老写法九项 ListViewViewPropTypesText.propTypesthis.refsmixinscomponentWillReceivePropscomponentWillMountgetDefaultPropsPlatform.OSmeasureNativeModulesModal—— 全部为空createClass精确命中 0、裸词也 0useNativeDriver3 处、都是true驱动的是Animated.Value正确用法三个组件全是函数组件typeof是 function、prototype是undefined—— 这次按真实形态断言一次全过核心判据是纯函数getStars()的 8 条整星 / 半星 / 四分之一星 /不传 step 时不出半星/ 0 分 / 满分 /maxStars可变 —— 全部命中。★★★★★ 一、预检干净但需要react-native-svg的 5 个符号预检项结果老写法九项createClass/React.PropTypes/ViewPropTypes/Text.propTypes/ 字符串 ref /this.refs/mixins/componentWillReceiveProps/componentWillMount/getDefaultProps✅✅全部为空ListView.DataSource/ListView✅ 空measure()/NativeModules/Modal✅ 全部空Platform.OS✅ 空平台差异交给I18nManagercreateClass✅精确 0、裸词 0useNativeDriver✅3 处都是trueonLayout3 处量容器宽度用于把手指位置换算成评分Animated10 处点击/拖动动画dependencies✅空peerDependencies⚠️react/react-native/react-native-svg外部 importreact/react-native/react-native-svgreact-native-svg的 5 个符号 —— 但现有桩能直接兜住源码src/StarIcon.tsxL3importSvg,{Path,Defs,LinearGradient,Stop}fromreact-native-svg;⇒ 需要Svg默认Path/Defs/LinearGradient/Stop共 5 个。而我工程里已有的 svg 桩是用Proxy兜底的consthandler{get:(_target,prop){if(prop__esModule)returntrue;if(propdefault)returnmakeStub(default);if(typeofpropsymbol)returnundefined;returnmakeStub(String(prop));// ← 任何具名导出都返回一个 View 桩},};module.exportsnewProxy({},handler);⇒⇒ 所以Path/Defs/LinearGradient/Stop全都能拿到都是View桩不需要改桩✓✓这条经验值得记用Proxy兜底的桩对图标/图形库这类符号很多但你只用到几个的依赖特别省事——换成逐个列出具名导出的写法每遇到一个新库就要补一次。★★★★★ 二、三个组件全是函数组件这次按真实形态断言一次全过先看源码坑 336 的固定动作src/StarRating.tsx L174: const StarRating ({...}) { src/StarIcon.tsx L125: const StarIcon ({...}) { src/StarRatingDisplay.tsx L75: const StarRatingDisplay ({...}) {⇒三个都是const X ({...}) {…}函数组件实测 9 条全 PASSNOTE | StarRating 的 typeof function PASS | ★★★ StarRating 是 function NOTE | StarRating.prototype 的 typeof undefined PASS | ★★★ StarRating 没有 prototype它是函数组件不是 class NOTE | StarIcon 的 typeof function PASS | ★★★ StarIcon 是 function NOTE | StarIcon.prototype 的 typeof undefined PASS | ★★★ StarIcon 没有 prototype它是函数组件不是 class NOTE | StarRatingDisplay 的 typeof function PASS | ★★★ StarRatingDisplay 是 function NOTE | StarRatingDisplay.prototype 的 typeof undefined PASS | ★★★ StarRatingDisplay 没有 prototype它是函数组件不是 class PASS | ★★ 入口默认导出非 null PASS | ★★ 具名 StarIcon 非 null PASS | ★★ 具名 StarRatingDisplay 非 null三档判别表已在三轮里全部实测过写法typeofprototypeprototype.render实测出处class X extends Componentfunctionobjectfunction某个表格库的Tableconst X ({…}) …functionundefinedundefined本轮三个组件、某个向导库X React.forwardRef(…)objectundefinedundefined某个下拉选择库、某个图片查看库⇒⇒ 固定动作先grep export default看那一行再选对应断言✓★★★★★ 三、核心判据getStars()纯函数的 8 条零设备依赖src/utils.tsexportfunctiongetStars(rating:number,maxStars:number,step?:half|quarter|full){return[...Array(maxStars)].map((_,i){constremainderrating-i;if(remainder1)returnfull;if(stepquarter){if(remainder0.75)returnthree-quarter;if(remainder0.5)returnhalf;if(remainder0.25)returnquarter;}elseif(stephalf){if(remainder0.5)returnhalf;}returnempty;});}我按这个逻辑手推出 8 组期望值实测全部命中#调用我推出的期望实测1getStars(3, 5)[full,full,full,empty,empty]✅2getStars(3.5, 5, half)[full,full,full,half,empty]✅3getStars(3.5, 5)不传 step[full,full,full,empty,empty]✅4getStars(2.75, 5, quarter)[full,full,three-quarter,empty,empty]✅5getStars(1.25, 5, quarter)[full,quarter,empty,empty,empty]✅6getStars(0, 5)5 个empty✅7getStars(5, 5)5 个full✅8getStars(2, 3)长度3✅第 3 条最有价值NOTE | getStars(3.5, 5)不传 step [full,full,full,empty,empty] PASS | ★★★ 不传 step ⇒ [full,full,full,empty,empty]第 4 颗不会变成 half⇒⇒ 同样是3.5分stephalf时第 4 颗是half、不传step时第 4 颗是empty✓✓⇒ 这说明step不是自动推断的必须显式传—— 一个读代码容易忽略、但实际会影响显示的细节 ✓第 4 条也很关键2.75stepquarter⇒ 第 3 颗是three-quarter因为remainder 0.75⇒ 0.75命中第一档✓★★ 四、精确默认值从.d.ts的default注释 源码读.d.ts的注释里直接写了默认值* default #fdd835 ← color * default color ← emptyColor默认跟随 color * default 5 ← maxStars * default 32 ← starSize源码里也能对上// src/StarRating.tsx L166constdefaultColor#fdd835;// src/StarIcon.tsx L12constRTL_TRANSFORM:ViewStyle{transform:[{rotateY:180deg}]};⇒color#fdd835Material 黄、maxStars5、starSize32✓★★★ 五、StarIcon的 5 种类型源码的类型定义src/StarIcon.tsxL9type:full|half|quarter|three-quarter|empty;⇒恰好 5 种与getStars()的返回值一一对应 ✓渲染上它们是这样实现的StarIcon.tsxL16-110StarBorder—— 星星轮廓Path描边StarFull—— 完整星星DefsLinearGradientPath渐变填充StarQuarter/StarThreeQuarter/StarHalf—— 用不同 offset 的LinearGradient实现部分填充⇒所以这个库对react-native-svg的依赖是真实功能性的不是可选美化——用桩隔离时会看到星星变成空白方块/View布局位置正确但图形不显示。这一点要在结论里说清楚组件结构可用但星星长什么样未经真实 SVG 验证。★ 六、其余预检结论预检项结果交付包lib/commonjs4 文件lib/modulelib/typescript全套.d.ts入口导出lib/commonjs/index.js800 B有3 个defaultStarRating/StarIcon/StarRatingDisplayStarRating的实现PanResponder拖动 Animated缩放 onLayout量宽 AccessibilityInfo无障碍播报AccessibilityInfo实现了increment/decrement/activate三种无障碍动作RTL 支持I18nManagerrotateY: 180deggetStars不在入口导出要走lib/commonjs/utils子路径七、接入与预检要点npminstallgithttps://atomgit.com/oh-react-native/react-native-star-rating-widget.git#1.11.0-ohos-1.0.0--ignore-scripts# ★ peerreact-native-svg真功能依赖⇒ 装官方鸿蒙版或用 Proxy 兜底的桩隔离八、交付包质量与基线说明类别结果交付包内容lib/commonjsindex/StarRating/StarIcon/StarRatingDisplay/utilslib/modulelib/typescript✓spec.json⚠️缺upstreamCommitvalidation⚠️build-pass-device-pending⚠️ 声明的基线reactNative: 0.88.0rnoh: 0.84.4⇒两字段自相矛盾备注库代码零改动关于基线本次验证在RN0.84.1 RNOH0.84.3上完成。本库零平台分支Platform.OS零命中、无原生代码⇒逻辑结论跨基线成立⚠️ 但**星星图形本身依赖react-native-svg**本轮用桩隔离 ⇒图形的真实渲染未验证。九、已知限制与本次验证边界9.1 用这个库要知道的事项说明★★★★★ 三个组件全是函数组件typeof是 function、prototype是undefined★★★★★step必须显式传同样是3.5分stephalf⇒ 第 4 颗half不传 ⇒ 第 4 颗empty★★★★★getStars是纯函数8 条判据全部可离线验证整星/半星/四分之一/0/满分/maxStars 可变★★★★react-native-svg是真功能依赖用了Svg/Path/Defs/LinearGradient/Stop5 个符号不是可选美化★★★★ 默认值color#fdd835/maxStars5/starSize32/emptyColor默认跟随color★★★ 5 种星星类型full | half | quarter | three-quarter | empty★★★ 入口 3 个导出默认StarRating 具名StarIcon/StarRatingDisplay★★getStars不在入口要走react-native-star-rating-widget/lib/commonjs/utils★★ 支持无障碍accessibilityRoleadjustableincrement/decrement/activate三种动作★★ RTL 支持I18nManagerrotateY: 180deg9.2 本次验证的边界★★★ 星星图形本身未验证react-native-svg用桩隔离 ⇒ 星星不显示图形只保留布局★★★accessibilityLabel里的%value%替换未在布局 dump 里观察到含 “STB” 的节点数为 0★★★ 未验证PanResponder拖动评分onChange未被真实触摸触发★★ 未验证Animated点击缩放动画useNativeDriver: true的那两条★★ 未验证StarRatingDisplay与StarRating的视觉差异桩下都是空白未验证enableSwiping/animationConfig/onRatingStart/onRatingEnd未验证RTLI18nManager强制 RTL下的rotateY效果未在RN 0.88.0/RNOH 0.84.4上复验未测其它屏幕宽度未做跨平台对照。库代码未改动用的是工程里已有的stubs/react-native-svg.js本轮没有新增/修改桩。十、常见问题Q1它在 RN 0.84 上能跑吗逻辑层能跑图形层未验证。14 条判据全 PASS三个组件都是函数组件、入口 3 个导出都在、getStars8 条全中LogBox无通知。但星星是 SVG 画的本轮把react-native-svg用Proxy桩隔离 ⇒只保证结构/布局不保证图形。Q2step到底要不要传要显式传。同样是3.5分getStars(3.5,5,half);// [full,full,full,half,empty] ← 第 4 颗是半星getStars(3.5,5);// [full,full,full,empty,empty] ← 第 4 颗是空星⇒ 不传step时不会自动推断出半星—— 这是实测确认的不是文档推测。Q3getStars怎么 import它不在入口导出要走子路径import{getStars}fromreact-native-star-rating-widget/lib/commonjs/utils;getStars(4.5,5,half);// [full,full,full,full,half]Q4默认值是多少color #fdd835Material 黄、maxStars 5、starSize 32、emptyColor默认跟随color。.d.ts的default注释与源码常量defaultColor一致Q5为什么用 svg 桩也能跑因为工程里的 svg 桩是Proxy兜底的 —— 任何具名导出都返回一个View桩module.exportsnewProxy({},{get:(_t,prop)prop__esModule?true:makeStub(String(prop)),});⇒Path/Defs/LinearGradient/Stop全部拿得到 ⇒模块图能解析、组件能渲染只是图形不显示。Q6StarIcon有哪些 type恰好 5 种full | half | quarter | three-quarter | empty—— 与getStars()的返回值一一对应。所以getStars的输出可以直接喂给StarIcon。Q7只显示不可交互怎么办用StarRatingDisplay它不接PanResponderimport {StarRatingDisplay} from react-native-star-rating-widget; StarRatingDisplay rating{3.5} starSize{28} stephalf /小结react-native-star-rating-widget是星级评分组件SVG 画星 PanResponder拖动 Animated缩放另提供只读的StarRatingDisplay。预检很干净、14 条判据零 FAIL。最值得记下来的是这几条★★★★★getStars()是纯函数8 条判据全 PASS —— 而且期望值全是手推的。整星 / 半星 / 四分之一 / 0 分 / 满分 /maxStars可变全部命中 ✓⇒ 其中最有价值的一条同样是3.5分stephalf时第 4 颗是half不传step时是empty⇒step不会自动推断—— 这是读代码容易漏、实际影响显示的细节靠实测才钉死 ✓★★★★★Proxy兜底的 svg 桩对符号多但只用几个的依赖特别省事。这个库要Svg/Path/Defs/LinearGradient/Stop5 个符号而工程里那份桩用Proxy把任何具名导出都变成View桩⇒一行都不用改✓⇒ 如果桩是逐个列举具名导出的写法每遇一个新库就要补一次。★★★★★ 三个组件全是函数组件按prototype undefined断言 ⇒ 9 条全过。⇒ 至此三档判别表已在三轮里全部实测class ⇒prototype.render是 function函数组件 ⇒prototype是undefinedforwardRef⇒typeof是object。★★★★ 诚实区分结构可用与图形未验证。星星是 SVG 画的本轮用桩隔离 ⇒布局/结构/逻辑已验证图形渲染未验证。⇒ 这类视觉强相关的库结论必须分层写否则读者会误以为星星能正常显示。★★★step这类看起来有默认行为的参数实测一下再下结论。我原本以为3.5分会自动显示半星 —— 实测不传step就是空星 ✗⇒“组件的名字里有 half” ≠ “它默认就是半星精度”✓★★accessibilityLabel的%value%替换没能在 dump 里看到。源码里是accessibilityLabel.replace(/%value%/g, stagedRating)逻辑上成立但布局 dump 里含 “STB” 的节点数为 0⇒ 如实记未观察到不当成结论 ✓本篇用到的库项内容三方库react-native-star-rating-widget上游1.11.0的鸿蒙适配版适配仓库https://atomgit.com/oh-react-native/react-native-star-rating-widget适配 TAG1.11.0-ohos-1.0.0需要 HAR / 权限 / ohpm都不需要纯 JS但依赖react-native-svg库类型星级评分SVG 画星 拖动 缩放动画 只读展示运行时依赖✅dependencies空peer 有react-native-svg真功能依赖导出形态默认StarRating 具名StarIcon/StarRatingDisplay三个都是函数组件核心纯函数getStars(rating, maxStars, step?)在lib/commonjs/utils入口未导出许可证MIT上游仓库https://github.com/bviebahn/react-native-star-rating-widget宿主工程RNOH084Demo测试页rnAppKey StarRatingTestAppnpminstallgithttps://atomgit.com/oh-react-native/react-native-star-rating-widget.git#1.11.0-ohos-1.0.0--ignore-scripts# peer react-native-svg 是真功能依赖 ⇒ 装官方鸿蒙版隔离验证可用 Proxy 兜底的桩import StarRating, {StarRatingDisplay, StarIcon} from react-native-star-rating-widget; import {getStars} from react-native-star-rating-widget/lib/commonjs/utils; // ① 可交互评分 StarRating rating{rating} onChange{(r) setRating(r)} maxStars{5} starSize{32} stephalf // ★ 不传就不会出半星 color#fdd835 / // ② 只读展示 StarRatingDisplay rating{3.5} starSize{28} stephalf / // ③ 单独用星星5 种 type StarIcon index{0} typehalf size{32} color#fdd835 / // ④ 纯函数把评分换算成星星类型数组 getStars(3.5, 5, half); // [full,full,full,half,empty] getStars(3.5, 5); // [full,full,full,empty,empty] ← ★ 不传 step getStars(2.75, 5, quarter);// [full,full,three-quarter,empty,empty] // ⚠️ 三个组件都是函数组件 ⇒ typeof 是 function、prototype 是 undefined // ⚠️ step 必须显式传不传 ⇒ 只出整星/空星不出半星 // ⚠️ react-native-svg 是真功能依赖Svg/Path/Defs/LinearGradient/Stop 5 个符号 // ⚠️ 默认值color#fdd835 / maxStars5 / starSize32 // ⚠️ StarIcon 的 type 恰好 5 种full / half / quarter / three-quarter / empty# 换页启动测试页 —— force-stop 不能省hdc shell aa force-stop com.rnoh084.demo hdc shell aa start-bcom.rnoh084.demo-aEntryAbility--psrnAppKey StarRatingTestApp判据的复现方式# ① 契约 getStars 8 条14 条全 PASShdc shellhilog -x | grep srw-test|Select-StringPASS|FAIL|SUMMARY|NOTE# ⇒ 三个组件都是 function 且 prototype 是 undefined# ⇒ getStars 8 条全部命中含不传 step ⇒ 不出 half验证环境项版本React Native0.84.1React19.2.3RNOHnpm / ohpmreact-native-oh/react-native-harmony/rnoh/react-native-openharmony0.84.3Node.js / npmv24.14.0/11.9.0DevEco Studio26.0.0.621HarmonyOS SDKAPI 2626.0.0.32设备HarmonyOS 7.0.0(26.0.0) Beta2 模拟器Pura X Viewohos-x641320×2232density 3本机状态栏高度117px 39vp宿主依赖✅ 复用已有stubs/react-native-svg.jsProxy 兜底本轮未改桩宿主 HAP 产物entry-default-signed.hap本次构建assembleHap3 分 50 秒⇒ 一次成功打包与构建退出码都检查了验证规模14/14 全 PASS、零 FAIL契约 9 getStars8 中重叠计三个组件都是函数组件getStars8 条全中LogBox无通知4 张截图互异⚠️星星图形未验证⚠️基线说明交付包spec.json声明RN 0.88.0 RNOH 0.84.4两字段自相矛盾本次验证在RN 0.84.1 RNOH 0.84.3上完成。逻辑结论跨基线成立图形渲染依赖react-native-svg本轮用桩隔离 ⇒ 未验证。相关社区与项目地址项目地址React Native 鸿蒙官方社区CPF-RNhttps://atomgit.com/CPF-RNRNOH 框架仓库https://atomgit.com/openharmony-RN/ohos_react_nativeRNOH 三方库使用文档https://atomgit.com/OpenHarmony-RN/usage-docsReact Native for OpenHarmony 组织https://atomgit.com/oh-react-nativeRN 三方库鸿蒙适配清单https://atomgit.com/oh-react-native/rn-ohos-adaptation-overview欢迎加入 CPF-RN 鸿蒙社区https://atomgit.com/CPF-RNReact Native for OpenHarmony 组织https://atomgit.com/oh-react-nativeRN 三方库鸿蒙适配清单https://atomgit.com/oh-react-native/rn-ohos-adaptation-overview