@mpxjs/webpack-plugin 2.9.64 → 2.9.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/lib/config.js +38 -10
  2. package/lib/index.js +5 -1
  3. package/lib/platform/style/wx/index.js +66 -60
  4. package/lib/platform/template/wx/index.js +12 -8
  5. package/lib/react/processTemplate.js +4 -2
  6. package/lib/react/style-helper.js +2 -5
  7. package/lib/runtime/components/react/context.ts +8 -0
  8. package/lib/runtime/components/react/dist/context.js +1 -0
  9. package/lib/runtime/components/react/dist/mpx-button.jsx +2 -1
  10. package/lib/runtime/components/react/dist/mpx-checkbox-group.jsx +2 -1
  11. package/lib/runtime/components/react/dist/mpx-checkbox.jsx +3 -2
  12. package/lib/runtime/components/react/dist/mpx-form.jsx +2 -1
  13. package/lib/runtime/components/react/dist/mpx-icon.jsx +3 -2
  14. package/lib/runtime/components/react/dist/mpx-image/index.jsx +2 -1
  15. package/lib/runtime/components/react/dist/mpx-input.jsx +2 -1
  16. package/lib/runtime/components/react/dist/mpx-label.jsx +2 -1
  17. package/lib/runtime/components/react/dist/mpx-movable-area.jsx +3 -2
  18. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +2 -1
  19. package/lib/runtime/components/react/dist/mpx-picker/date.jsx +2 -1
  20. package/lib/runtime/components/react/dist/mpx-picker/index.jsx +2 -1
  21. package/lib/runtime/components/react/dist/mpx-picker/multiSelector.jsx +2 -1
  22. package/lib/runtime/components/react/dist/mpx-picker/region.jsx +2 -1
  23. package/lib/runtime/components/react/dist/mpx-picker/selector.jsx +2 -1
  24. package/lib/runtime/components/react/dist/mpx-picker/time.jsx +4 -2
  25. package/lib/runtime/components/react/dist/mpx-picker-view-column.jsx +3 -2
  26. package/lib/runtime/components/react/dist/mpx-picker-view.jsx +2 -1
  27. package/lib/runtime/components/react/dist/mpx-radio-group.jsx +2 -1
  28. package/lib/runtime/components/react/dist/mpx-radio.jsx +3 -2
  29. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +13 -3
  30. package/lib/runtime/components/react/dist/mpx-swiper/carouse.jsx +78 -77
  31. package/lib/runtime/components/react/dist/mpx-swiper/index.jsx +2 -1
  32. package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +3 -2
  33. package/lib/runtime/components/react/dist/mpx-switch.jsx +3 -2
  34. package/lib/runtime/components/react/dist/mpx-text.jsx +2 -1
  35. package/lib/runtime/components/react/dist/mpx-view.jsx +45 -15
  36. package/lib/runtime/components/react/dist/mpx-web-view.jsx +4 -3
  37. package/lib/runtime/components/react/dist/useAnimationHooks.js +215 -0
  38. package/lib/runtime/components/react/dist/useNodesRef.js +1 -5
  39. package/lib/runtime/components/react/dist/utils.jsx +50 -37
  40. package/lib/runtime/components/react/mpx-button.tsx +3 -1
  41. package/lib/runtime/components/react/mpx-checkbox-group.tsx +3 -1
  42. package/lib/runtime/components/react/mpx-checkbox.tsx +4 -1
  43. package/lib/runtime/components/react/mpx-form.tsx +2 -1
  44. package/lib/runtime/components/react/mpx-icon.tsx +3 -2
  45. package/lib/runtime/components/react/mpx-image/index.tsx +2 -1
  46. package/lib/runtime/components/react/mpx-input.tsx +2 -1
  47. package/lib/runtime/components/react/mpx-label.tsx +2 -1
  48. package/lib/runtime/components/react/mpx-movable-area.tsx +3 -2
  49. package/lib/runtime/components/react/mpx-movable-view.tsx +2 -1
  50. package/lib/runtime/components/react/mpx-picker/date.tsx +2 -1
  51. package/lib/runtime/components/react/mpx-picker/index.tsx +2 -1
  52. package/lib/runtime/components/react/mpx-picker/multiSelector.tsx +2 -1
  53. package/lib/runtime/components/react/mpx-picker/region.tsx +2 -1
  54. package/lib/runtime/components/react/mpx-picker/selector.tsx +2 -1
  55. package/lib/runtime/components/react/mpx-picker/time.tsx +4 -2
  56. package/lib/runtime/components/react/mpx-picker-view-column.tsx +3 -2
  57. package/lib/runtime/components/react/mpx-picker-view.tsx +2 -1
  58. package/lib/runtime/components/react/mpx-radio-group.tsx +2 -1
  59. package/lib/runtime/components/react/mpx-radio.tsx +3 -2
  60. package/lib/runtime/components/react/mpx-scroll-view.tsx +14 -2
  61. package/lib/runtime/components/react/mpx-swiper/carouse.tsx +77 -75
  62. package/lib/runtime/components/react/mpx-swiper/index.tsx +4 -1
  63. package/lib/runtime/components/react/mpx-swiper-item.tsx +2 -1
  64. package/lib/runtime/components/react/mpx-switch.tsx +2 -1
  65. package/lib/runtime/components/react/mpx-text.tsx +2 -1
  66. package/lib/runtime/components/react/mpx-view.tsx +55 -23
  67. package/lib/runtime/components/react/mpx-web-view.tsx +4 -3
  68. package/lib/runtime/components/react/types/common.ts +8 -2
  69. package/lib/runtime/components/react/types/global.d.ts +11 -1
  70. package/lib/runtime/components/react/useAnimationHooks.ts +248 -0
  71. package/lib/runtime/components/react/useNodesRef.ts +1 -6
  72. package/lib/runtime/components/react/utils.tsx +71 -50
  73. package/lib/runtime/components/web/mpx-scroll-view.vue +25 -5
  74. package/lib/style-compiler/index.js +5 -4
  75. package/lib/template-compiler/compiler.js +127 -158
  76. package/lib/utils/const.js +2 -1
  77. package/lib/web/processStyles.js +6 -2
  78. package/lib/web/processTemplate.js +2 -3
  79. package/lib/wxml/loader.js +1 -1
  80. package/package.json +6 -4
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { View, LayoutChangeEvent } from 'react-native'
6
- import { JSX, useState, useEffect, forwardRef, ReactNode } from 'react'
6
+ import { JSX, useState, useEffect, forwardRef, ReactNode, useRef } from 'react'
7
7
  import useNodesRef, { HandlerRef } from './useNodesRef'
8
8
  import useInnerProps from './getInnerListeners'
9
9
  import { MovableAreaContext } from './context'
@@ -41,7 +41,8 @@ const _MovableArea = forwardRef<HandlerRef<View, MovableAreaProps>, MovableAreaP
41
41
  setHeight
42
42
  } = useTransformStyle(style, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
43
43
 
44
- const { nodeRef: movableViewRef } = useNodesRef(props, ref)
44
+ const movableViewRef = useRef(null)
45
+ useNodesRef(props, ref, movableViewRef)
45
46
 
46
47
  const onLayout = (e: LayoutChangeEvent) => {
47
48
  const { width = 10, height = 10 } = e.nativeEvent.layout
@@ -84,7 +84,8 @@ const _MovableView = forwardRef<HandlerRef<View, MovableViewProps>, MovableViewP
84
84
  y: Number(y)
85
85
  })
86
86
 
87
- const { nodeRef } = useNodesRef(props, ref, {
87
+ const nodeRef = useRef<View>(null)
88
+ useNodesRef(props, ref, nodeRef, {
88
89
  defaultStyle: styles.container
89
90
  })
90
91
 
@@ -31,7 +31,8 @@ const _DatePicker = forwardRef<HandlerRef<View, DateProps>, DateProps>((props: D
31
31
  const [datevalue, setDateValue] = useState(value)
32
32
  // 存储layout布局信息
33
33
  const layoutRef = useRef({})
34
- const { nodeRef: viewRef } = useNodesRef<View, DateProps>(props, ref, {
34
+ const viewRef = useRef<View>(null)
35
+ useNodesRef<View, DateProps>(props, ref, viewRef, {
35
36
  })
36
37
 
37
38
  useEffect(() => {
@@ -34,7 +34,8 @@ import { FormContext, FormFieldValue } from '../context'
34
34
  const _Picker = forwardRef<HandlerRef<View, PickerProps>, PickerProps>((props: PickerProps, ref): React.JSX.Element => {
35
35
  const { mode = 'selector', value, bindcancel, bindchange, children, bindcolumnchange } = props
36
36
  const innerLayout = useRef({})
37
- const { nodeRef } = useNodesRef<View, PickerProps>(props, ref, {
37
+ const nodeRef = useRef(null)
38
+ useNodesRef<View, PickerProps>(props, ref, nodeRef, {
38
39
  })
39
40
  const innerProps = useInnerProps(props, {
40
41
  ref: nodeRef
@@ -89,7 +89,8 @@ const _MultiSelectorPicker = forwardRef<HandlerRef<View, MultiSelectorProps>, Mu
89
89
  const [data, setData] = useState(formatRange || [])
90
90
  // 存储layout布局信息
91
91
  const layoutRef = useRef({})
92
- const { nodeRef: viewRef } = useNodesRef<View, MultiSelectorProps>(props, ref, {
92
+ const viewRef = useRef<View>(null)
93
+ useNodesRef<View, MultiSelectorProps>(props, ref, viewRef, {
93
94
  })
94
95
 
95
96
  useEffect(() => {
@@ -44,7 +44,8 @@ const _RegionPicker = forwardRef<HandlerRef<View, RegionProps>, RegionProps>((pr
44
44
  const [regionvalue, setRegionValue] = useState(value)
45
45
  // 存储layout布局信息
46
46
  const layoutRef = useRef({})
47
- const { nodeRef: viewRef } = useNodesRef<View, RegionProps>(props, ref, {
47
+ const viewRef = useRef<View>(null)
48
+ useNodesRef<View, RegionProps>(props, ref, viewRef, {
48
49
  })
49
50
 
50
51
  const onChange = (value: string[]): void => {
@@ -31,7 +31,8 @@ const _SelectorPicker = forwardRef<HandlerRef<View, SelectorProps>, SelectorProp
31
31
  const [data, setData] = useState(formatRange || [])
32
32
  // 存储layout布局信息
33
33
  const layoutRef = useRef({})
34
- const { nodeRef: viewRef } = useNodesRef<View, SelectorProps>(props, ref, {
34
+ const viewRef = useRef<View>(null)
35
+ useNodesRef<View, SelectorProps>(props, ref, viewRef, {
35
36
  })
36
37
 
37
38
  useEffect(() => {
@@ -134,10 +134,12 @@ const _TimePicker = forwardRef<HandlerRef<View, TimeProps>, TimeProps>((props: T
134
134
  const [timevalue, setTimeValue] = useState(defaultValue)
135
135
  // 存储layout布局信息
136
136
  const layoutRef = useRef({})
137
- const { nodeRef: viewRef } = useNodesRef<View, TimeProps>(props, ref, {})
137
+ const viewRef = useRef<View>(null)
138
+ useNodesRef<View, TimeProps>(props, ref, viewRef, {})
138
139
  // 存储modal的布局信息
139
140
  const modalLayoutRef = useRef({})
140
- const { nodeRef: modalRef } = useNodesRef<View, TimeProps>(props, ref, {})
141
+ const modalRef = useRef<View>(null)
142
+ useNodesRef<View, TimeProps>(props, ref, modalRef, {})
141
143
  const [visible, setVisible] = useState(false)
142
144
  const columnData = generateColumns()
143
145
  const [data, setData] = useState(columnData)
@@ -1,6 +1,6 @@
1
1
 
2
2
  import { View, Animated, SafeAreaView, NativeScrollEvent, NativeSyntheticEvent, LayoutChangeEvent, ScrollView } from 'react-native'
3
- import React, { forwardRef, useState, useEffect, ReactElement, ReactNode } from 'react'
3
+ import React, { forwardRef, useRef, useState, useEffect, ReactElement, ReactNode } from 'react'
4
4
  import { useTransformStyle, splitStyle, splitProps, wrapChildren, useLayout } from './utils'
5
5
  import useNodesRef, { HandlerRef } from './useNodesRef' // 引入辅助函数
6
6
  interface ColumnProps {
@@ -38,7 +38,8 @@ const _PickerViewColumn = forwardRef<HandlerRef<ScrollView & View, ColumnProps>,
38
38
  const { textProps } = splitProps(props)
39
39
  // const { innerStyle } = splitStyle(normalStyle)
40
40
  // scrollView的ref
41
- const { nodeRef: scrollViewRef } = useNodesRef(props, ref, {})
41
+ const scrollViewRef = useRef<ScrollView>(null)
42
+ useNodesRef(props, ref, scrollViewRef, {})
42
43
  // 每个元素的高度
43
44
  let [itemH, setItemH] = useState(0)
44
45
 
@@ -66,7 +66,8 @@ const _PickerView = forwardRef<HandlerRef<View, PickerViewProps>, PickerViewProp
66
66
  // 微信设置到pick-view上上设置的normalStyle如border等需要转换成RN的style然后进行透传
67
67
  const indicatorStyle = parseInlineStyle(props['indicator-style'])
68
68
  const { height: indicatorH, width: indicatorW } = indicatorStyle
69
- const { nodeRef } = useNodesRef<View, PickerViewProps>(props, ref, {})
69
+ const nodeRef = useRef(null)
70
+ useNodesRef<View, PickerViewProps>(props, ref, nodeRef, {})
70
71
  // picker-view 设置的color等textStyle,在小程序上的表现是可以继承到最内层的text样式, 但是RN内部column是slot无法设置, 需要业务自己在column内的元素上设置
71
72
  const {
72
73
  normalStyle,
@@ -65,7 +65,8 @@ const radioGroup = forwardRef<
65
65
  setHeight
66
66
  } = useTransformStyle(styleObj, { enableVar, externalVarContext, parentFontSize, parentWidth, parentHeight })
67
67
 
68
- const { nodeRef } = useNodesRef(props, ref, { defaultStyle })
68
+ const nodeRef = useRef(null)
69
+ useNodesRef(props, ref, nodeRef, { defaultStyle })
69
70
 
70
71
  const { layoutRef, layoutStyle, layoutProps } = useLayout({ props, hasSelfPercent, setWidth, setHeight, nodeRef })
71
72
 
@@ -4,7 +4,7 @@
4
4
  * ✔ checked
5
5
  * ✔ color
6
6
  */
7
- import { JSX, useState, forwardRef, useEffect, ReactNode, useContext, Dispatch, SetStateAction } from 'react'
7
+ import { JSX, useRef, useState, forwardRef, useEffect, ReactNode, useContext, Dispatch, SetStateAction } from 'react'
8
8
  import { View, StyleSheet, ViewStyle, NativeSyntheticEvent } from 'react-native'
9
9
  import { warn } from '@mpxjs/utils'
10
10
  import { LabelContext, RadioGroupContext } from './context'
@@ -141,7 +141,8 @@ const Radio = forwardRef<HandlerRef<View, RadioProps>, RadioProps>(
141
141
  warn('Radio does not support background image-related styles!')
142
142
  }
143
143
 
144
- const { nodeRef } = useNodesRef(props, ref, {
144
+ const nodeRef = useRef(null)
145
+ useNodesRef(props, ref, nodeRef, {
145
146
  defaultStyle,
146
147
  change: onChange
147
148
  })
@@ -33,11 +33,13 @@
33
33
  */
34
34
  import { ScrollView } from 'react-native-gesture-handler'
35
35
  import { View, RefreshControl, NativeSyntheticEvent, NativeScrollEvent, LayoutChangeEvent, ViewStyle } from 'react-native'
36
- import { JSX, ReactNode, RefObject, useRef, useState, useEffect, forwardRef } from 'react'
36
+ import { JSX, ReactNode, RefObject, useRef, useState, useEffect, forwardRef, useContext } from 'react'
37
+ import { useAnimatedRef } from 'react-native-reanimated'
37
38
  import { warn } from '@mpxjs/utils'
38
39
  import useInnerProps, { getCustomEvent } from './getInnerListeners'
39
40
  import useNodesRef, { HandlerRef } from './useNodesRef'
40
41
  import { splitProps, splitStyle, useTransformStyle, useLayout, wrapChildren } from './utils'
42
+ import { IntersectionObserverContext } from './context'
41
43
 
42
44
  interface ScrollViewProps {
43
45
  children?: ReactNode;
@@ -59,6 +61,7 @@ interface ScrollViewProps {
59
61
  'scroll-top'?: number;
60
62
  'scroll-left'?: number;
61
63
  'enable-offset'?: boolean;
64
+ 'enable-trigger-intersection-observer'?: boolean;
62
65
  'enable-var'?: boolean;
63
66
  'external-var-context'?: Record<string, any>;
64
67
  'parent-font-size'?: number;
@@ -106,6 +109,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
106
109
  'scroll-x': scrollX = false,
107
110
  'scroll-y': scrollY = false,
108
111
  'enable-back-to-top': enableBackToTop = false,
112
+ 'enable-trigger-intersection-observer': enableTriggerIntersectionObserver = false,
109
113
  'paging-enabled': pagingEnabled = false,
110
114
  'upper-threshold': upperThreshold = 50,
111
115
  'lower-threshold': lowerThreshold = 50,
@@ -138,6 +142,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
138
142
  const hasCallScrollToUpper = useRef(true)
139
143
  const hasCallScrollToLower = useRef(false)
140
144
  const initialTimeout = useRef<ReturnType<typeof setTimeout> | null>(null)
145
+ const intersectionObservers = useContext(IntersectionObserverContext)
141
146
 
142
147
  const {
143
148
  normalStyle,
@@ -150,7 +155,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
150
155
 
151
156
  const { textStyle, innerStyle } = splitStyle(normalStyle)
152
157
 
153
- const { nodeRef: scrollViewRef } = useNodesRef(props, ref, {
158
+ const scrollViewRef = useAnimatedRef<ScrollView>()
159
+ useNodesRef(props, ref, scrollViewRef, {
154
160
  scrollOffset: scrollOptions,
155
161
  node: {
156
162
  scrollEnabled: scrollX || scrollY,
@@ -283,6 +289,11 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
283
289
  }, props)
284
290
  )
285
291
  updateScrollOptions(e, { scrollLeft, scrollTop })
292
+ if (enableTriggerIntersectionObserver && intersectionObservers) {
293
+ for (const key in intersectionObservers) {
294
+ intersectionObservers[key].throttleMeasure()
295
+ }
296
+ }
286
297
  }
287
298
 
288
299
  function onScrollEnd (e: NativeSyntheticEvent<NativeScrollEvent>) {
@@ -405,6 +416,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
405
416
  'scroll-x',
406
417
  'scroll-y',
407
418
  'enable-back-to-top',
419
+ 'enable-trigger-intersection-observer',
408
420
  'paging-enabled',
409
421
  'show-scrollbar',
410
422
  'upper-threshold',
@@ -87,9 +87,12 @@ const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, Carouse
87
87
  const initOffsetIndex = initIndex + (props.circular && totalElements > 1 ? 1 : 0)
88
88
  const defaultX = (defaultWidth * initOffsetIndex) || 0
89
89
  const defaultY = (defaultHeight * initOffsetIndex) || 0
90
+ // 主动scorllTo时是否要出发onScrollEnd
91
+ const needTriggerScrollEnd = useRef(true)
90
92
  // 内部存储上一次的offset值
91
93
  const autoplayTimerRef = useRef<ReturnType <typeof setTimeout> | null>(null)
92
- const { nodeRef: scrollViewRef } = useNodesRef<ScrollView & View, CarouseProps>(props, ref, {})
94
+ const scrollViewRef = useRef<ScrollView & View>(null)
95
+ useNodesRef<ScrollView & View, CarouseProps>(props, ref, scrollViewRef, {})
93
96
  const {
94
97
  // 存储layout布局信息
95
98
  layoutRef,
@@ -99,22 +102,21 @@ const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, Carouse
99
102
  // 内部存储上一次的偏移量
100
103
  const internalsRef = useRef({
101
104
  offset: {
102
- x: defaultX || 0,
103
- y: defaultY || 0
105
+ x: 0,
106
+ y: 0
104
107
  },
105
108
  isScrolling: false
106
109
  })
107
110
  const isDragRef = useRef(false)
108
111
  const [state, setState] = useState({
109
- children: newChild,
110
112
  width: dir === 'x' && typeof defaultWidth === 'number' ? defaultWidth - previousMargin - nextMargin : defaultWidth,
111
113
  height: dir === 'y' && typeof defaultHeight === 'number' ? defaultHeight - previousMargin - nextMargin : defaultHeight,
112
114
  // 真正的游标索引, 从0开始
113
115
  index: initIndex,
114
116
  total: totalElements,
115
117
  offset: {
116
- x: dir === 'x' ? defaultX : 0,
117
- y: dir === 'y' ? defaultY : 0
118
+ x: 0,
119
+ y: 0
118
120
  },
119
121
  dir
120
122
  } as CarouseState)
@@ -137,25 +139,38 @@ const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, Carouse
137
139
 
138
140
  useEffect(() => {
139
141
  // 确认这个是变化的props变化的时候才执行,还是初始化的时候就执行
140
- if (!props.autoplay && props.current !== state.index) {
142
+ if (!props.autoplay && props.current !== undefined && props.current !== state.index) {
141
143
  const initIndex = props.current || 0
142
144
  // 这里要排除超过元素个数的设置
143
- const initOffsetIndex = initIndex + (props.circular && totalElements > 1 ? 1 : 0)
144
- const defaultX = (defaultWidth * initOffsetIndex) || 0
145
- const offset = {
146
- x: dir === 'x' ? defaultX : 0,
147
- y: dir === 'y' ? defaultY : 0
145
+ const { nextIndex, nextOffset } = getMultiNextConfig(props.current)
146
+ // 1. 安卓需要主动更新下内部状态, 2. IOS不能触发完wcrollTo之后立即updateState, 会造成滑动两次
147
+ // 2. setTimeout 是fix 当再渲染过程中触发scrollTo失败的问题
148
+ if (Platform.OS === 'ios') {
149
+ needTriggerScrollEnd.current = false
150
+ setTimeout(() => {
151
+ scrollViewRef.current?.scrollTo({
152
+ ...nextOffset,
153
+ animated: true
154
+ })
155
+ }, 50)
156
+ } else {
157
+ updateState(nextIndex, nextOffset)
148
158
  }
149
- state.offset = offset
150
- internalsRef.current.offset = offset
151
- setState((preState) => {
152
- return {
153
- ...preState,
154
- offset
155
- }
156
- })
157
159
  }
158
- }, [props.current])
160
+ }, [props.current, state.width, state.height])
161
+
162
+ function getMultiNextConfig (target: number) {
163
+ const step = state.dir === 'x' ? state.width : state.height
164
+ const targetPos = step * props.current
165
+ const targetOffset = {
166
+ x: dir === 'x' ? targetPos : 0,
167
+ y: dir === 'y' ? targetPos : 0
168
+ }
169
+ return {
170
+ nextIndex: target,
171
+ nextOffset: targetOffset
172
+ }
173
+ }
159
174
  /**
160
175
  * @desc: 更新状态: index和offset, 并响应索引变化的事件
161
176
  * scrollViewOffset: 移动到的目标位置
@@ -207,7 +222,6 @@ const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, Carouse
207
222
  nextIndex = isBack ? nextIndex - 2 : nextIndex
208
223
  }
209
224
  if (!props.circular) {
210
- // nextIndex = isBack ? nextIndex - 2 : nextIndex
211
225
  nextOffset = Object.assign({}, currentOffset, { [state.dir]: step * nextIndex })
212
226
  } else {
213
227
  if (isBack) {
@@ -253,13 +267,12 @@ const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, Carouse
253
267
  createAutoPlay()
254
268
  return
255
269
  }
256
- if (!Array.isArray(state.children)) {
270
+ if (!Array.isArray(props.children)) {
257
271
  return
258
272
  }
259
273
  const step = state.dir === 'x' ? state.width : state.height
260
274
  const { nextOffset, autoMoveOffset, isAutoEnd } = getNextConfig(state.offset)
261
275
  // 这里可以scroll到下一个元素, 但是把scrollView的偏移量在设置为content,视觉效果就没了吧
262
- // scrollViewRef.current?.scrollTo({ x: nextOffset['x'], y: nextOffset['y'], animated: true })
263
276
  if (Platform.OS === 'ios') {
264
277
  if (!isAutoEnd) {
265
278
  scrollViewRef.current?.scrollTo({ x: nextOffset.x, y: nextOffset.y, animated: true })
@@ -285,7 +298,6 @@ const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, Carouse
285
298
  // 安卓无法实现视觉的无缝连接, 只能回到真正的位置, 且安卓调用scrollTo不能触发onMomentumScrollEnd,还未找到为啥
286
299
  if (state.dir === 'x') {
287
300
  scrollViewRef.current?.scrollTo({ x: step, y: step, animated: true })
288
- // scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: autoMoveOffset.y, animated: true })
289
301
  } else {
290
302
  scrollViewRef.current?.scrollTo({ x: autoMoveOffset.x, y: step, animated: true })
291
303
  }
@@ -303,9 +315,15 @@ const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, Carouse
303
315
 
304
316
  /**
305
317
  * 当用户开始拖动结束
318
+ * 注意: 当手动调用scrollTo的时候, 安卓不会触发onMomentumScrollEnd, IOS会触发onMomentumScrollEnd
306
319
  */
307
320
  function onScrollEnd (event: NativeSyntheticEvent<NativeScrollEvent>) {
308
- // 这里安卓好像没有触发onScrollEnd, 调用scrollTo的时候
321
+ if (Platform.OS === 'ios' && !needTriggerScrollEnd.current) {
322
+ const { nextIndex, nextOffset } = getMultiNextConfig(props.current)
323
+ updateState(nextIndex, nextOffset)
324
+ needTriggerScrollEnd.current = true
325
+ return
326
+ }
309
327
  if (totalElements === 1) {
310
328
  return
311
329
  }
@@ -333,57 +351,41 @@ const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, Carouse
333
351
  * @desc: 水平方向时,获取元素的布局,更新, 其中如果传递100%时需要依赖measure计算元算的宽高
334
352
  */
335
353
  function onWrapperLayout (e: LayoutChangeEvent) {
336
- if (hasSelfPercent) {
337
- const { width, height } = e?.nativeEvent?.layout || {}
338
- setWidth(width || 0)
339
- setHeight(height || 0)
340
- }
341
- if (props.enableOffset) {
342
- scrollViewRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
343
- layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
344
- const isWDiff = state.width !== width
345
- const isHDiff = state.height !== height
346
- if (isWDiff || isHDiff) {
347
- const changeState = {
348
- width: isWDiff ? width : state.width,
349
- height: isHDiff ? height : state.height
350
- }
351
- const attr = state.dir === 'x' ? 'width' : 'height'
352
- changeState[attr] = changeState[attr] - previousMargin - nextMargin
353
- const correctOffset = Object.assign({}, state.offset, {
354
- [state.dir]: initOffsetIndex * (state.dir === 'x' ? changeState.width : changeState.height)
355
- })
356
- state.offset = correctOffset
357
- state.width = changeState.width
358
- state.height = changeState.height
359
- setState((preState) => {
360
- return {
361
- ...preState,
362
- offset: correctOffset,
363
- width: changeState.width,
364
- height: changeState.height
365
- }
366
- })
367
- scrollViewRef.current?.scrollTo({ x: correctOffset.x, y: correctOffset.y, animated: false })
354
+ scrollViewRef.current?.measure((x: number, y: number, width: number, height: number, offsetLeft: number, offsetTop: number) => {
355
+ layoutRef.current = { x, y, width, height, offsetLeft, offsetTop }
356
+ const isWDiff = state.width !== width
357
+ const isHDiff = state.height !== height
358
+ if (isWDiff || isHDiff) {
359
+ const changeState = {
360
+ width: isWDiff ? width : state.width,
361
+ height: isHDiff ? height : state.height
368
362
  }
369
- props.getInnerLayout && props.getInnerLayout(layoutRef)
370
- })
371
- }
363
+ const attr = state.dir === 'x' ? 'width' : 'height'
364
+ changeState[attr] = changeState[attr] - previousMargin - nextMargin
365
+ const correctOffset = Object.assign({}, state.offset, {
366
+ [state.dir]: initOffsetIndex * (state.dir === 'x' ? changeState.width : changeState.height)
367
+ })
368
+ state.width = changeState.width
369
+ state.height = changeState.height
370
+ // 这里setState之后,会再触发重新渲染, renderScrollView会再次触发onScrollEnd,
371
+ setState((preState) => {
372
+ return {
373
+ ...preState,
374
+ width: changeState.width,
375
+ height: changeState.height
376
+ }
377
+ })
378
+ }
379
+ props.getInnerLayout && props.getInnerLayout(layoutRef)
380
+ })
372
381
  }
373
382
 
374
383
  function getOffset (): Array<number> {
375
384
  const step = state.dir === 'x' ? state.width : state.height
376
385
  if (!step || Number.isNaN(+step)) return []
377
386
  const offsetArray = []
378
- if (previousMargin) {
379
- offsetArray.push(0)
380
- for (let i = 1; i < totalElements; i++) {
381
- offsetArray.push(i * step - previousMargin)
382
- }
383
- } else {
384
- for (let i = 0; i < totalElements; i++) {
385
- offsetArray.push(i * step)
386
- }
387
+ for (let i = 0; i < totalElements; i++) {
388
+ offsetArray.push(i * step)
387
389
  }
388
390
  return offsetArray
389
391
  }
@@ -393,7 +395,7 @@ const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, Carouse
393
395
  const scrollElementProps = {
394
396
  ref: scrollViewRef,
395
397
  horizontal: props.horizontal,
396
- pagingEnabled: false,
398
+ pagingEnabled: true,
397
399
  snapToOffsets: offsetsArray,
398
400
  decelerationRate: 0.99, // 'fast'
399
401
  showsHorizontalScrollIndicator: false,
@@ -460,20 +462,21 @@ const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, Carouse
460
462
  }
461
463
 
462
464
  function renderPages () {
463
- const { width, height, total, children } = state
465
+ const { width, height } = state
466
+ const { children } = props
464
467
  const { circular } = props
465
468
  const pageStyle = { width: width, height: height }
466
469
  // 设置了previousMargin或者nextMargin,
467
470
  // 1. 元素的宽度是减去这两个数目之和
468
471
  // 2. previousMargin设置marginLeft正值, nextmargin设置marginRight负值
469
472
  // 3. 第一个元素设置previousMargin 和 nextMargin, 最后一个元素
470
- if (total > 1 && Array.isArray(children)) {
473
+ if (totalElements > 1 && Array.isArray(children)) {
471
474
  let arrElements: (Array<ReactNode>) = []
472
475
  // pages = ["2", "0", "1", "2", "0"]
473
476
  const pages = Array.isArray(children) ? Object.keys(children) : []
474
477
  /* 无限循环的时候 */
475
478
  if (circular) {
476
- pages.unshift(total - 1 + '')
479
+ pages.unshift(totalElements - 1 + '')
477
480
  pages.push('0')
478
481
  }
479
482
  arrElements = pages.map((page, i) => {
@@ -485,7 +488,6 @@ const _Carouse = forwardRef<HandlerRef<ScrollView & View, CarouseProps>, Carouse
485
488
  } else if (i === pages.length - 1 && typeof width === 'number') {
486
489
  nextMargin && (extraStyle.marginRight = nextMargin)
487
490
  }
488
- // return (<View style={[pageStyle, styles.slide, extraStyle]} key={ 'page' + i}>{children[+page]}</View>)
489
491
  return (<View style={[pageStyle, styles.slide, extraStyle]} key={ 'page' + i}>
490
492
  {wrapChildren(
491
493
  {
@@ -45,7 +45,10 @@ const _SwiperWrapper = forwardRef<HandlerRef<ScrollView, SwiperProps>, SwiperPro
45
45
  bindchange: props.bindchange,
46
46
  easingFunction: props['easing-function'] || 'default'
47
47
  }
48
- const { nodeRef } = useNodesRef<ScrollView, SwiperProps>(props, ref, {})
48
+
49
+ const nodeRef = useRef(null)
50
+ useNodesRef<ScrollView, SwiperProps>(props, ref, nodeRef, {})
51
+
49
52
  const innerProps = useInnerProps(props, {
50
53
  ref: nodeRef
51
54
  }, [
@@ -25,7 +25,8 @@ const _SwiperItem = forwardRef<HandlerRef<View, SwiperItemProps>, SwiperItemProp
25
25
  } = props
26
26
 
27
27
  const { textProps } = splitProps(props)
28
- const { nodeRef } = useNodesRef(props, ref, {})
28
+ const nodeRef = useRef(null)
29
+ useNodesRef(props, ref, nodeRef, {})
29
30
 
30
31
  const {
31
32
  normalStyle,
@@ -76,7 +76,8 @@ const _Switch = forwardRef<HandlerRef<Switch, _SwitchProps>, _SwitchProps>((prop
76
76
  setIsChecked(checked)
77
77
  }, [checked])
78
78
 
79
- const { nodeRef } = useNodesRef<Switch, _SwitchProps>(props, ref)
79
+ const nodeRef = useRef(null)
80
+ useNodesRef<Switch, _SwitchProps>(props, ref, nodeRef)
80
81
 
81
82
  const {
82
83
  layoutRef,
@@ -48,7 +48,8 @@ const _Text = forwardRef<HandlerRef<Text, _TextProps>, _TextProps>((props, ref):
48
48
  parentHeight
49
49
  })
50
50
 
51
- const { nodeRef } = useNodesRef<Text, _TextProps>(props, ref)
51
+ const nodeRef = useRef(null)
52
+ useNodesRef<Text, _TextProps>(props, ref, nodeRef)
52
53
 
53
54
  const innerProps = useInnerProps(props, {
54
55
  ref: nodeRef,