swiper / swiper-item — 实现与 components.md 对照

对照基准:

模板 kebab-case;组件 properties camelCase;adapter / host 仅 kebab-case


结论摘要

维度 结论
原生节点 swiperViewPagerswiper-itemViewPagerItem
已贯通 currentautoplayintervaldurationcircularverticaldisplay-multiple-itemsprevious-marginnext-margindisable-touchindicator-dotsindicator-colorindicator-active-color + bindchange / bindtransition / bindanimationfinish
item-id / currentItemId itemId 存于 ViewPagerItem;pageSelected / animationfinish 按当前 index 回填 currentItemId
Demo 正向(含 indicator 配色切换、itemId 事件)+ 异常("false" 字符串 Boolean、非法 current / circular)

属性对照

swiper

属性(模板) 规格默认 components.md 当前实现 原生 / Hippy
indicator-dots false ✅ → indicatorDots ArkUI indicator / SetShowIndicator
indicator-color rgba(0,0,0,0.3) ✅ → ARGB → DotIndicator / OH_ArkUI_SwiperIndicator_SetColor adapter parseColorValue
indicator-active-color #0A59F7 ✅ → ARGB → selectedColor / SetSelectedColor 同上
current 0 ✅ → current(首帧无动画;之后变更带动画) 首帧/initialPageSetSwiperIndex;其后 currentSwipeToIndex(...,1) / changeIndex(true);同 index 短路
autoplay false ✅ → autoPlay NODE_SWIPER_AUTO_PLAY / .autoPlay
interval 5000 NODE_SWIPER_INTERVAL / .interval
duration 500 NODE_SWIPER_DURATION / .duration(须配合非弹簧 curve,见下)
circular false ✅ → circular/loop SetSwiperLoop / .loop
vertical false Hippy direction=vertical / .vertical
display-multiple-items 1 NODE_SWIPER_DISPLAY_COUNT / .displayCount
previous-margin "0px" ✅ → previousMargin SetSwiperPrevMargin
next-margin "0px" ✅ → nextMargin SetSwiperNextMargin
disable-touch false ✅ → disableTouch(= !scrollEnabled) Hippy scrollEnabled

swiper-item

属性 规格 当前实现
item-id 可选标识 ✅ → itemId(C++/ETS 存储;事件按 index 查询)

事件对照

ASCF Native wire detail
bindchange pageSelected(wire: pageselected { current, currentItemId, source }source=touch/autoplay/""(setData·setPage 等)
bindtransition pageScroll(wire: pagescroll { dx, dy }(横向 offset→dx;纵向 offset→dy;payload 带 vertical
bindanimationfinish animationfinishOnAnimationEnd { current, currentItemId, source }(与 change 同源)

组件 def 声明 events:FlexUI 无该字段;监听由模板 bind:* → NBE setListenerStats + adapter eventNamesMap 注册(与 scroll-view 相同)。


实现要点

  1. Boolean !! / Number 串optionalTypes:[String] 接住模板属性串(含 interval="{{5000}}")。Boolean 字符串 "false"!! 为真(异常 Demo)。Number 非法串(如 interval="abc")仍回退默认值;devNODE_ENV !== 'production')下 triggerWarning 提示,production 静默。
  2. margin:adapter 解析 px/rpx → 逻辑 px,再交 native DpToVprpx 复用 FlexUIBridge.getDimensions().width / 750(与 StyleResolver 约定一致;dims 缺失时 width fallback=375,等价旧 /2)。样式路径的 rpx 字符串仍透传 native;此处因 margin 属性走 float prop,必须在 JS 侧先换算。
  3. 改 adapter / frontendcompile-builtins + frontend build + build-jsfwk;改 C++/ETS → HAP
  4. LITE 白名单build-profile.json5LITE_COMPONENTSBuildConfig.ets 必须包含 ViewPager,ViewPagerItem,否则 CreateRenderView 返回空 → Demo 空白
  5. displayCount>1 / 纵向均分 — 强依赖 NBE Yoga %(C++/ETS 不自行按 N 算格子主轴)
    • NBENativeBackendElement._applyViewPagerItemSlotSize 读父级 display-multiple-items + vertical,把 item 主轴写成 100/N%(横→width,纵→height),交叉轴缺省 100%setData 改 display/vertical 后靠每次 resolveNativeProps 覆盖生效。
    • C++ PagerItemViewSetHeight(frame.height) + SetWidthPercent(1.0) —— 高度/Yoga 帧来自上游;displayCount_ 做纵向 heightPercent
    • ETS FRViewPagerItemcssHeight = frame.height,再 .width('100%').height(cssHeight) —— 同上。
    • 结论vertical && display-multiple-items>1 时格子主轴尺寸只靠 NBE Yoga %;缺 _applyViewPagerItemSlotSize% 未进 Yoga,C++/ETS 无法补救,子树仍按整页排版并裁切。swiper-item 禁止 position:absolute 全铺。
  6. current:首帧 / initialPage → C++ SetSwiperIndex、ETS changeIndex(false)(无动画);之后的 current 变更 → SwipeToIndex(i,1) / changeIndex(true)。同 index 短路(挡住 onChange→setData 回灌)。C++ 先写 index_;ETS 动画路径先写 pendingIndex 做短路,this.index 仍由 onChangesettleIndex 回写(避免 .index() 绑定冲动画)
  7. indicator 配色:adapter parseColorValue → ARGB;C++ NODE_SWIPER_INDICATOR + OH_ArkUI_SwiperIndicator_SetColor/SetSelectedColor;ETS Indicator.dot().color().selectedColor()
  8. currentItemId:子项存 itemIdpageSelected / animationfinish 按当前 index 查子项回填
  9. source:Touch Down → touch;无 touch 且 autoPlayautoplaycurrent/setPage 等程序切页 → ""pageSelected 每次重算写入;animationfinish 读同轮值后清空,避免下一轮仍报上一轮 touch
  10. 事件名 wire:JS eventNamesMap 必须用小写 wire 名(pageselected / pagescroll)。DispatchEvent 会 toLowerCase;驼峰 pageSelected 会导致 reverse map 失败、bindchange 不触发。
  11. 手势 bindchange:ETS 受控 .index() 下拖动常不回调 onChangeonAnimationEnd 在落点 ≠ 已 settle index 时补发 pageSelected(与程序切页 onChange 去重,取消回弹不发)。
  12. 把 ViewPager 加进 ETS_ONLY_RENDER_VIEWS(C++ 已注册)
  13. duration:ArkUI Swiper 默认 interpolatingSpring 不受 duration 控制;ETS .curve(Curve.Linear) / C++ NODE_SWIPER_CURVE=LINEAR,ASCF duration(ms)才生效。
  14. bindtransition:native pageScroll;ETS onContentDidScroll(滑动全程)+ onAnimationEnd|offset|≤0.05 时补发终态 pageScroll(offset=0)(对齐 C++);JS 须 transition→pagescroll

Demo 覆盖

  • 正向:华为示例动态面板(dots / 配色 / autoplay / circular / vertical / current / interval / duration / display / margins / disable-touch)+ 三事件(status 展示 itemId
  • 异常:autoplay="false"current="abc"vertical="false"circular="abc"