@@ -5,7 +5,7 @@ import Animated, { useAnimatedStyle, useSharedValue, withTiming, Easing, runOnJS
55import React , { JSX , forwardRef , useRef , useEffect , ReactNode , ReactElement , useMemo , createElement } from 'react'
66import useInnerProps , { getCustomEvent } from './getInnerListeners'
77import useNodesRef , { HandlerRef } from './useNodesRef' // 引入辅助函数
8- import { useTransformStyle , splitStyle , splitProps , useLayout , wrapChildren , extendObject , GestureHandler , flatGesture } from './utils'
8+ import { useTransformStyle , splitStyle , splitProps , useLayout , wrapChildren , extendObject , GestureHandler , flatGesture , useRunOnJSCallback } from './utils'
99import { SwiperContext } from './context'
1010import Portal from './mpx-portal'
1111/**
@@ -148,6 +148,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
148148 autoplay = false ,
149149 circular = false ,
150150 disableGesture = false ,
151+ current : propCurrent = 0 ,
151152 bindchange
152153 } = props
153154 const easeingFunc = props [ 'easing-function' ] || 'default'
@@ -198,10 +199,10 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
198199 // 每个元素的宽度 or 高度,有固定值直接初始化无则0
199200 const step = useSharedValue ( initStep )
200201 // 记录选中元素的索引值
201- const currentIndex = useSharedValue ( props . current || 0 )
202+ const currentIndex = useSharedValue ( propCurrent )
202203 // const initOffset = getOffset(props.current || 0, initStep)
203204 // 记录元素的偏移量
204- const offset = useSharedValue ( getOffset ( props . current || 0 , initStep ) )
205+ const offset = useSharedValue ( getOffset ( propCurrent , initStep ) )
205206 const strAbso = 'absolute' + dir . toUpperCase ( ) as StrAbsoType
206207 const strVelocity = 'velocity' + dir . toUpperCase ( ) as StrVelocityType
207208 // 标识手指触摸和抬起, 起点在onBegin
@@ -270,7 +271,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
270271 const iStep = dir === 'x' ? realWidth : realHeight
271272 if ( iStep !== step . value ) {
272273 step . value = iStep
273- updateCurrent ( props . current || 0 , iStep )
274+ updateCurrent ( propCurrent , iStep )
274275 updateAutoplay ( )
275276 }
276277 }
@@ -374,7 +375,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
374375 easing : easeMap [ easeingFunc ]
375376 } , ( ) => {
376377 currentIndex . value = nextIndex
377- runOnJS ( loop ) ( )
378+ runOnJS ( runOnJSCallback ) ( 'loop' )
378379 } )
379380 } else {
380381 // 默认向右, 向下
@@ -389,7 +390,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
389390 // 将开始位置设置为真正的位置
390391 offset . value = initOffset
391392 currentIndex . value = nextIndex
392- runOnJS ( loop ) ( )
393+ runOnJS ( runOnJSCallback ) ( 'loop' )
393394 } )
394395 } else {
395396 nextIndex = currentIndex . value + 1
@@ -400,7 +401,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
400401 easing : easeMap [ easeingFunc ]
401402 } , ( ) => {
402403 currentIndex . value = nextIndex
403- runOnJS ( loop ) ( )
404+ runOnJS ( runOnJSCallback ) ( 'loop' )
404405 } )
405406 }
406407 }
@@ -428,13 +429,21 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
428429 }
429430 } , [ ] )
430431
431- function handleSwiperChange ( current : number ) {
432- if ( props . current !== currentIndex . value ) {
432+ function handleSwiperChange ( current : number , pCurrent : number ) {
433+ if ( pCurrent !== currentIndex . value ) {
433434 const eventData = getCustomEvent ( 'change' , { } , { detail : { current, source : 'touch' } , layoutRef : layoutRef } )
434435 bindchange && bindchange ( eventData )
435436 }
436437 }
437438
439+ const runOnJSCallbackRef = useRef ( {
440+ loop,
441+ pauseLoop,
442+ resumeLoop,
443+ handleSwiperChange
444+ } )
445+ const runOnJSCallback = useRunOnJSCallback ( runOnJSCallbackRef )
446+
438447 function getOffset ( index : number , stepValue : number ) {
439448 if ( ! stepValue ) return 0
440449 let targetOffset = 0
@@ -451,12 +460,12 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
451460 const targetOffset = getOffset ( index || 0 , stepValue )
452461 if ( targetOffset !== offset . value ) {
453462 // 内部基于props.current!==currentIndex.value决定是否使用动画及更新currentIndex.value
454- if ( props . current !== undefined && props . current !== currentIndex . value ) {
463+ if ( propCurrent !== undefined && propCurrent !== currentIndex . value ) {
455464 offset . value = withTiming ( targetOffset , {
456465 duration : easeDuration ,
457466 easing : easeMap [ easeingFunc ]
458467 } , ( ) => {
459- currentIndex . value = props . current || 0
468+ currentIndex . value = propCurrent
460469 } )
461470 } else {
462471 offset . value = targetOffset
@@ -474,7 +483,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
474483 useAnimatedReaction ( ( ) => currentIndex . value , ( newIndex : number , preIndex : number ) => {
475484 // 这里必须传递函数名, 直接写()=> {}形式会报 访问了未sharedValue信息
476485 if ( newIndex !== preIndex && bindchange ) {
477- runOnJS ( handleSwiperChange ) ( newIndex )
486+ runOnJS ( runOnJSCallback ) ( 'handleSwiperChange' , newIndex , propCurrent )
478487 }
479488 } )
480489
@@ -510,10 +519,10 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
510519 useEffect ( ( ) => {
511520 // 1. 如果用户在touch的过程中, 外部更新了current以外部为准(小程序表现)
512521 // 2. 手指滑动过程中更新索引,外部会把current再传入进来,导致offset直接更新,增加判断不同才更新
513- if ( props . current !== currentIndex . value ) {
514- updateCurrent ( props . current || 0 , step . value )
522+ if ( propCurrent !== currentIndex . value ) {
523+ updateCurrent ( propCurrent , step . value )
515524 }
516- } , [ props . current ] )
525+ } , [ propCurrent ] )
517526
518527 useEffect ( ( ) => {
519528 autoplayShared . value = autoplay
@@ -603,7 +612,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
603612 if ( touchfinish . value !== false ) {
604613 currentIndex . value = selectedIndex
605614 offset . value = resetOffset
606- runOnJS ( resumeLoop ) ( )
615+ runOnJS ( runOnJSCallback ) ( 'resumeLoop' )
607616 }
608617 } )
609618 } else {
@@ -613,7 +622,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
613622 } , ( ) => {
614623 if ( touchfinish . value !== false ) {
615624 currentIndex . value = selectedIndex
616- runOnJS ( resumeLoop ) ( )
625+ runOnJS ( runOnJSCallback ) ( 'resumeLoop' )
617626 }
618627 } )
619628 }
@@ -635,7 +644,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
635644 } , ( ) => {
636645 if ( touchfinish . value !== false ) {
637646 currentIndex . value = moveToIndex
638- runOnJS ( resumeLoop ) ( )
647+ runOnJS ( runOnJSCallback ) ( 'resumeLoop' )
639648 }
640649 } )
641650 }
@@ -662,19 +671,10 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
662671 'worklet'
663672 const { diffOffset, half, isTriggerUpdateHalf } = computeHalf ( eventData )
664673 if ( + diffOffset === 0 ) {
665- runOnJS ( resumeLoop ) ( )
674+ runOnJS ( runOnJSCallback ) ( 'resumeLoop' )
666675 } else if ( isTriggerUpdateHalf ) {
667- // 如果触发了onUpdate时的索引变更,则直接以update时的index为准
668- const targetIndex = ! circularShared . value ? currentIndex . value : currentIndex . value + patchElmNumShared . value - 1
669- offset . value = withTiming ( - targetIndex * step . value , {
670- duration : easeDuration ,
671- easing : easeMap [ easeingFunc ]
672- } , ( ) => {
673- if ( touchfinish . value !== false ) {
674- currentIndex . value = targetIndex
675- runOnJS ( resumeLoop ) ( )
676- }
677- } )
676+ // 如果触发了onUpdate时的索引变更
677+ handleEnd ( eventData )
678678 } else if ( half ) {
679679 handleEnd ( eventData )
680680 } else {
@@ -745,14 +745,14 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
745745 if ( ! step . value ) return
746746 touchfinish . value = false
747747 cancelAnimation ( offset )
748- runOnJS ( pauseLoop ) ( )
748+ runOnJS ( runOnJSCallback ) ( 'pauseLoop' )
749749 preAbsolutePos . value = e [ strAbso ]
750750 moveTranstion . value = e [ strAbso ]
751751 } )
752752 . onUpdate ( ( e : GestureStateChangeEvent < PanGestureHandlerEventPayload > ) => {
753753 'worklet'
754- if ( touchfinish . value ) return
755754 const moveDistance = e [ strAbso ] - preAbsolutePos . value
755+ if ( touchfinish . value || moveDistance === 0 ) return
756756 const eventData = {
757757 translation : moveDistance ,
758758 transdir : moveDistance
0 commit comments