@mpxjs/webpack-plugin 2.10.15-5 → 2.10.15

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 (27) hide show
  1. package/LICENSE +433 -0
  2. package/lib/index.js +2 -5
  3. package/lib/platform/template/wx/component-config/progress.js +12 -0
  4. package/lib/platform/template/wx/component-config/unsupported.js +1 -1
  5. package/lib/platform/template/wx/index.js +3 -1
  6. package/lib/runtime/components/react/dist/getInnerListeners.js +35 -21
  7. package/lib/runtime/components/react/dist/mpx-movable-view.jsx +102 -34
  8. package/lib/runtime/components/react/dist/mpx-portal/portal-manager.jsx +3 -5
  9. package/lib/runtime/components/react/dist/mpx-progress.jsx +159 -0
  10. package/lib/runtime/components/react/dist/mpx-scroll-view.jsx +38 -7
  11. package/lib/runtime/components/react/dist/mpx-swiper.jsx +9 -16
  12. package/lib/runtime/components/react/dist/mpx-web-view.jsx +20 -1
  13. package/lib/runtime/components/react/getInnerListeners.ts +41 -22
  14. package/lib/runtime/components/react/mpx-movable-view.tsx +156 -48
  15. package/lib/runtime/components/react/mpx-portal/portal-manager.tsx +4 -8
  16. package/lib/runtime/components/react/mpx-progress.tsx +257 -0
  17. package/lib/runtime/components/react/mpx-scroll-view.tsx +39 -7
  18. package/lib/runtime/components/react/mpx-swiper.tsx +9 -16
  19. package/lib/runtime/components/react/mpx-web-view.tsx +22 -1
  20. package/lib/runtime/components/react/types/getInnerListeners.d.ts +7 -2
  21. package/lib/runtime/components/web/mpx-movable-area.vue +43 -19
  22. package/lib/runtime/components/web/mpx-movable-view.vue +93 -3
  23. package/lib/runtime/components/web/mpx-swiper.vue +1 -2
  24. package/lib/runtime/components/web/mpx-web-view.vue +3 -3
  25. package/lib/template-compiler/compiler.js +61 -31
  26. package/lib/wxss/utils.js +1 -1
  27. package/package.json +3 -3
@@ -194,6 +194,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
194
194
  white: ['#fff']
195
195
  }
196
196
 
197
+ const isContentSizeChange = useRef(false)
198
+
197
199
  const { refresherContent, otherContent } = getRefresherContent(props.children)
198
200
  const hasRefresher = refresherContent && refresherEnabled
199
201
 
@@ -379,7 +381,22 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
379
381
  }
380
382
 
381
383
  function onContentSizeChange (width: number, height: number) {
382
- scrollOptions.current.contentLength = selectLength({ height, width })
384
+ isContentSizeChange.current = true
385
+ const newContentLength = selectLength({ height, width })
386
+ const oldContentLength = scrollOptions.current.contentLength
387
+ scrollOptions.current.contentLength = newContentLength
388
+ // 内容高度变化时,Animated.event 的映射可能会有不生效的场景,所以需要手动设置一下 scrollOffset 的值
389
+ if (enableSticky && (__mpx_mode__ === 'android' || __mpx_mode__ === 'ios')) {
390
+ // 当内容变少时,检查当前滚动位置是否超出新的内容范围
391
+ if (newContentLength < oldContentLength) {
392
+ const { visibleLength, offset } = scrollOptions.current
393
+ const maxOffset = Math.max(0, newContentLength - visibleLength)
394
+ // 如果当前滚动位置超出了新的内容范围,调整滚动offset
395
+ if (offset > maxOffset && scrollY) {
396
+ scrollOffset.setValue(maxOffset)
397
+ }
398
+ }
399
+ }
383
400
  }
384
401
 
385
402
  function onLayout (e: LayoutChangeEvent) {
@@ -402,8 +419,9 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
402
419
 
403
420
  function onScroll (e: NativeSyntheticEvent<NativeScrollEvent>) {
404
421
  const { bindscroll } = props
405
- const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset
406
- const { width: scrollWidth, height: scrollHeight } = e.nativeEvent.contentSize
422
+ const { contentOffset, layoutMeasurement, contentSize } = e.nativeEvent
423
+ const { x: scrollLeft, y: scrollTop } = contentOffset
424
+ const { width: scrollWidth, height: scrollHeight } = contentSize
407
425
  isAtTop.value = scrollTop <= 0
408
426
  bindscroll &&
409
427
  bindscroll(
@@ -414,7 +432,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
414
432
  scrollHeight,
415
433
  scrollWidth,
416
434
  deltaX: scrollLeft - scrollOptions.current.scrollLeft,
417
- deltaY: scrollTop - scrollOptions.current.scrollTop
435
+ deltaY: scrollTop - scrollOptions.current.scrollTop,
436
+ layoutMeasurement
418
437
  },
419
438
  layoutRef
420
439
  }, props)
@@ -429,8 +448,9 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
429
448
 
430
449
  function onScrollEnd (e: NativeSyntheticEvent<NativeScrollEvent>) {
431
450
  const { bindscrollend } = props
432
- const { x: scrollLeft, y: scrollTop } = e.nativeEvent.contentOffset
433
- const { width: scrollWidth, height: scrollHeight } = e.nativeEvent.contentSize
451
+ const { contentOffset, layoutMeasurement, contentSize } = e.nativeEvent
452
+ const { x: scrollLeft, y: scrollTop } = contentOffset
453
+ const { width: scrollWidth, height: scrollHeight } = contentSize
434
454
  isAtTop.value = scrollTop <= 0
435
455
  bindscrollend &&
436
456
  bindscrollend(
@@ -439,7 +459,8 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
439
459
  scrollLeft,
440
460
  scrollTop,
441
461
  scrollHeight,
442
- scrollWidth
462
+ scrollWidth,
463
+ layoutMeasurement
443
464
  },
444
465
  layoutRef
445
466
  }, props)
@@ -494,6 +515,16 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
494
515
  {
495
516
  useNativeDriver: true,
496
517
  listener: (event: NativeSyntheticEvent<NativeScrollEvent>) => {
518
+ const y = event.nativeEvent.contentOffset.y || 0
519
+ // 内容高度变化时,鸿蒙中 listener 回调通过scrollOffset.__getValue获取值一直等于event.nativeEvent.contentOffset.y,值是正确的,但是无法触发 sticky 动画执行,所以需要手动再 set 一次
520
+ if (__mpx_mode__ === 'harmony') {
521
+ if (isContentSizeChange.current) {
522
+ scrollOffset.setValue(y)
523
+ setTimeout(() => {
524
+ isContentSizeChange.current = false
525
+ }, 100)
526
+ }
527
+ }
497
528
  onScroll(event)
498
529
  }
499
530
  }
@@ -702,6 +733,7 @@ const _ScrollView = forwardRef<HandlerRef<ScrollView & View, ScrollViewProps>, S
702
733
  showsVerticalScrollIndicator: scrollY && showScrollbar,
703
734
  scrollEnabled: !enableScroll ? false : !!(scrollX || scrollY),
704
735
  bounces: false,
736
+ overScrollMode: 'never',
705
737
  ref: scrollViewRef,
706
738
  onScroll: enableSticky ? scrollHandler : onScroll,
707
739
  onContentSizeChange: onContentSizeChange,
@@ -207,8 +207,6 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
207
207
  const strVelocity = 'velocity' + dir.toUpperCase() as StrVelocityType
208
208
  // 标识手指触摸和抬起, 起点在onBegin
209
209
  const touchfinish = useSharedValue(true)
210
- // 记录onUpdate时的方向,用于进行onFinalize中的值修正
211
- const preUpdateTransDir = useSharedValue(0)
212
210
  // 记录上一帧的绝对定位坐标
213
211
  const preAbsolutePos = useSharedValue(0)
214
212
  // 记录从onBegin 到 onTouchesUp 时移动的距离
@@ -431,9 +429,11 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
431
429
  }
432
430
  }, [])
433
431
 
434
- function handleSwiperChange (current: number) {
435
- const eventData = getCustomEvent('change', {}, { detail: { current, source: 'touch' }, layoutRef: layoutRef })
436
- bindchange && bindchange(eventData)
432
+ function handleSwiperChange (current: number, pCurrent: number) {
433
+ if (pCurrent !== currentIndex.value) {
434
+ const eventData = getCustomEvent('change', {}, { detail: { current, source: 'touch' }, layoutRef: layoutRef })
435
+ bindchange && bindchange(eventData)
436
+ }
437
437
  }
438
438
 
439
439
  const runOnJSCallbackRef = useRef({
@@ -482,7 +482,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
482
482
  // 1. 用户在当前页切换选中项,动画;用户携带选中index打开到swiper页直接选中不走动画
483
483
  useAnimatedReaction(() => currentIndex.value, (newIndex: number, preIndex: number) => {
484
484
  // 这里必须传递函数名, 直接写()=> {}形式会报 访问了未sharedValue信息
485
- if (newIndex !== preIndex && preIndex !== null && preIndex !== undefined && bindchange) {
485
+ if (newIndex !== preIndex && bindchange) {
486
486
  runOnJS(runOnJSCallback)('handleSwiperChange', newIndex, propCurrent)
487
487
  }
488
488
  })
@@ -517,9 +517,9 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
517
517
  }, [children.length])
518
518
 
519
519
  useEffect(() => {
520
- // 1. 如果用户在touch的过程中, 外部更新了current以内部为准(小程序表现)
520
+ // 1. 如果用户在touch的过程中, 外部更新了current以外部为准(小程序表现)
521
521
  // 2. 手指滑动过程中更新索引,外部会把current再传入进来,导致offset直接更新,增加判断不同才更新
522
- if (propCurrent !== currentIndex.value && touchfinish.value) {
522
+ if (propCurrent !== currentIndex.value) {
523
523
  updateCurrent(propCurrent, step.value)
524
524
  }
525
525
  }, [propCurrent])
@@ -757,7 +757,6 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
757
757
  translation: moveDistance,
758
758
  transdir: moveDistance
759
759
  }
760
- preUpdateTransDir.value = moveDistance
761
760
  // 1. 支持滑动中超出一半更新索引的能力:只更新索引并不会影响onFinalize依据当前offset计算的索引
762
761
  const { half } = computeHalf(eventData)
763
762
  if (childrenLength.value > 1 && half) {
@@ -795,17 +794,11 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
795
794
  'worklet'
796
795
  if (touchfinish.value) return
797
796
  touchfinish.value = true
798
- /**
799
- * 安卓修正
800
- * 问题:部分安卓机型onFinalize中拿到的absoluteX 有问题
801
- * 案例:比如手指从右向左滑的时候,onUpdate拿到的是241.64346313476562, 而onFinalize中拿到的是241.81817626953125,理论上onFinalize中应该比onUpdate小才对吧
802
- * 解决方式:修正
803
- */
804
797
  // 触发过onUpdate正常情况下e[strAbso] - preAbsolutePos.value=0; 未触发过onUpdate的情况下e[strAbso] - preAbsolutePos.value 不为0
805
798
  const moveDistance = e[strAbso] - preAbsolutePos.value
806
799
  const eventData = {
807
800
  translation: moveDistance,
808
- transdir: Math.abs(moveDistance) > 1 ? moveDistance : preUpdateTransDir.value
801
+ transdir: moveDistance !== 0 ? moveDistance : e[strAbso] - moveTranstion.value
809
802
  }
810
803
  // 1. 只有一个元素:循环 和 非循环状态,都走回弹效果
811
804
  if (childrenLength.value === 1) {
@@ -76,6 +76,7 @@ const styles = StyleSheet.create({
76
76
  borderRadius: 10
77
77
  }
78
78
  })
79
+
79
80
  const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((props, ref): JSX.Element | null => {
80
81
  const { src, bindmessage, bindload, binderror } = props
81
82
  const mpx = global.__mpx
@@ -126,10 +127,27 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
126
127
  style: defaultWebViewStyle
127
128
  })
128
129
 
130
+ const hostValidate = (url: string) => {
131
+ const host = url && new URL(url).host
132
+ const hostWhitelists = mpx.config.rnConfig?.webviewConfig?.hostWhitelists || []
133
+ if (hostWhitelists.length) {
134
+ return hostWhitelists.some((item: string) => {
135
+ return host.endsWith(item)
136
+ })
137
+ } else {
138
+ return true
139
+ }
140
+ }
141
+
129
142
  if (!src) {
130
143
  return null
131
144
  }
132
145
 
146
+ if (!hostValidate(src)) {
147
+ console.error('访问页面域名不符合domainWhiteLists白名单配置,请确认是否正确配置该域名白名单')
148
+ return null
149
+ }
150
+
133
151
  const _reload = function () {
134
152
  if (__mpx_mode__ !== 'ios') {
135
153
  fristLoaded.current = false // 安卓需要重新设置
@@ -182,6 +200,9 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
182
200
  }
183
201
  }
184
202
  const _message = function (res: WebViewMessageEvent) {
203
+ if (!hostValidate(res.nativeEvent?.url)) {
204
+ return
205
+ }
185
206
  let data: MessageData = {}
186
207
  let asyncCallback
187
208
  const navObj = promisify({ redirectTo, navigateTo, navigateBack, reLaunch, switchTab })
@@ -232,7 +253,7 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
232
253
  break
233
254
  default:
234
255
  if (type) {
235
- const implement = mpx.config.webviewConfig.apiImplementations && mpx.config.webviewConfig.apiImplementations[type]
256
+ const implement = mpx.config.rnConfig.webviewConfig && mpx.config.rnConfig.webviewConfig.apiImplementations && mpx.config.rnConfig.webviewConfig.apiImplementations[type]
236
257
  if (isFunction(implement)) {
237
258
  asyncCallback = Promise.resolve(implement(...params))
238
259
  } else {
@@ -84,12 +84,16 @@ interface ExtendedNativeTouchEvent extends NativeTouchEvent {
84
84
  _stoppedEventTypes?: Set<string>
85
85
  }
86
86
 
87
+ interface GlobalEventState {
88
+ needPress: boolean
89
+ identifier: null | number
90
+ }
91
+
87
92
  export {
88
93
  NativeTouchEvent,
89
94
  Props,
90
95
  AdditionalProps,
91
96
  RemoveProps,
92
- UseInnerPropsConfig,
93
97
  InnerRef,
94
98
  LayoutRef,
95
99
  PropsRef,
@@ -98,5 +102,6 @@ export {
98
102
  ExtendedNativeTouchEvent,
99
103
  EventConfig,
100
104
  RawConfig,
101
- EventType
105
+ EventType,
106
+ GlobalEventState
102
107
  }
@@ -1,21 +1,23 @@
1
1
  <template>
2
- <div class="mpx-movable-area-container" ref="movableArea">
3
- <div class="mpx-movable-scroll-wrapper" ref="scroll">
4
- <slot></slot>
5
- </div>
2
+ <div class="mpx-movable-area-container" ref="movableArea">
3
+ <div class="mpx-movable-scroll-wrapper" ref="scroll">
4
+ <slot></slot>
6
5
  </div>
6
+ </div>
7
7
  </template>
8
8
 
9
9
  <script type="text/ecmascript-6">
10
10
  export default {
11
- data () {
12
- return {}
11
+ data() {
12
+ return {
13
+ isInited: false,
14
+ }
13
15
  },
14
- mounted () {
16
+ mounted() {
15
17
  this.computedStyle()
16
- },
17
- beforeDestroy () {
18
-
18
+ if (!this.closeResizeObserver) {
19
+ this.createResizeObserver()
20
+ }
19
21
  },
20
22
  methods: {
21
23
  computedStyle() {
@@ -26,17 +28,39 @@
26
28
  if (!style.height) {
27
29
  this.$refs.movableArea.style.height = '10px'
28
30
  }
31
+ },
32
+ createResizeObserver() {
33
+ if (typeof ResizeObserver !== 'undefined') {
34
+ this.resizeObserver = new ResizeObserver(entries => {
35
+ if (!this.isInited) {
36
+ this.isInited = true
37
+ return
38
+ }
39
+ this.$children.forEach(child => {
40
+ if (child && child.refresh) {
41
+ child.refresh()
42
+ }
43
+ })
44
+ })
45
+ this.resizeObserver.observe(this.$refs.movableArea)
46
+ }
47
+ },
48
+ },
49
+ beforeDestroy () {
50
+ if (this.resizeObserver) {
51
+ this.resizeObserver.disconnect()
52
+ this.resizeObserver = null
29
53
  }
30
- }
54
+ },
31
55
  }
32
56
  </script>
33
57
  <style lang="stylus" rel="stylesheet/stylus" scoped>
34
- .mpx-movable-area-container
35
- position: absolute
36
- .mpx-movable-scroll-wrapper
37
- position: absolute
38
- top: 0
39
- left: 0
40
- bottom: 0
41
- right: 0
58
+ .mpx-movable-area-container
59
+ position: relative
60
+ .mpx-movable-scroll-wrapper
61
+ position: absolute
62
+ top: 0
63
+ left: 0
64
+ bottom: 0
65
+ right: 0
42
66
  </style>
@@ -38,7 +38,13 @@ export default {
38
38
  touchEvent: '',
39
39
  isInited: false,
40
40
  deactivatedX: 0,
41
- deactivatedY: 0
41
+ deactivatedY: 0,
42
+ // 缓存高度,用于检测变化
43
+ cachedContentHeight: 0,
44
+ cachedWrapperHeight: 0,
45
+ // 缓存宽度,用于检测变化
46
+ cachedContentWidth: 0,
47
+ cachedWrapperWidth: 0
42
48
  }
43
49
  },
44
50
  props: {
@@ -107,7 +113,24 @@ export default {
107
113
  },
108
114
  watch: {
109
115
  x (newVal) {
116
+ if (this.direction === 'vertical' || this.direction === 'none') {
117
+ return
118
+ }
110
119
  this.source = ''
120
+ // 检查宽度是否发生变化,只有在变化时才调用 refresh
121
+ const widthChanged = this.checkWidthChange()
122
+ let currentX = this.bs.x
123
+
124
+ if (widthChanged) {
125
+ // 兼容容器尺寸变化且同时改变x的场景,ResizeObserver回调是异步的,如果不直接refresh,minScrollX, maxScrollX 拿到的都是上一次的值
126
+ this.refresh()
127
+ // bs refresh 方法内会触发 resetPosition(),如果容器宽度从 100 - 50,y 从 100 - 50,这会导致位置立即跳转到边界内,没有动画效果,造成视觉突兀
128
+ // 如果 refresh 导致了位置变化,先恢复到原位置再动画滚动
129
+ if (this.bs.x !== currentX) {
130
+ this.bs.scrollTo(currentX, this.bs.y, 0)
131
+ }
132
+ }
133
+
111
134
  if (newVal > this.bs.minScrollX) {
112
135
  newVal = this.bs.minScrollX
113
136
  }
@@ -118,7 +141,24 @@ export default {
118
141
  this.bs.scrollTo(newVal, this.bs.y, this.speed)
119
142
  },
120
143
  y (newVal) {
144
+ if (this.direction === 'horizontal' || this.direction === 'none') {
145
+ return
146
+ }
121
147
  this.source = ''
148
+ // 检查高度是否发生变化,只有在变化时才调用 refresh
149
+ const heightChanged = this.checkHeightChange()
150
+ let currentY = this.bs.y
151
+
152
+ if (heightChanged) {
153
+ // 兼容容器尺寸变化且同时改变y的场景,ResizeObserver回调是异步的,如果不直接refresh,minScrollY, maxScrollY 拿到的都是上一次的值
154
+ this.refresh()
155
+ // bs refresh 方法内会触发 resetPosition(),如果容器高度从 100 - 50,y 从 100 - 50,这会导致位置立即跳转到边界内,没有动画效果,造成视觉突兀
156
+ // 如果 refresh 导致了位置变化,先恢复到原位置再动画滚动
157
+ if (this.bs.y !== currentY) {
158
+ this.bs.scrollTo(this.bs.x, currentY, 0)
159
+ }
160
+ }
161
+
122
162
  if (newVal > this.bs.minScrollY) {
123
163
  newVal = this.bs.minScrollY
124
164
  }
@@ -146,6 +186,10 @@ export default {
146
186
  if (!this.scrollOptions.closeResizeObserver) {
147
187
  this.createResizeObserver()
148
188
  }
189
+ // 初始化尺寸缓存
190
+ this.$nextTick(() => {
191
+ this.initSizeCache()
192
+ })
149
193
  this.init()
150
194
  },
151
195
  activated () {
@@ -178,13 +222,50 @@ export default {
178
222
  }
179
223
  this.refresh()
180
224
  })
181
- const elementToObserve = document.querySelector('.mpx-movable-scroll-content')
182
- elementToObserve && this.resizeObserver.observe(elementToObserve)
225
+ this.resizeObserver.observe(this.$refs.scrollContent)
183
226
  }
184
227
  },
185
228
  refresh () {
186
229
  this.bs && this.bs.refresh()
187
230
  },
231
+ // 检查高度是否发生变化
232
+ checkHeightChange () {
233
+ if (!this.$refs.scrollContent || !this.$parent.$refs.movableArea) {
234
+ return false
235
+ }
236
+
237
+ const currentContentHeight = this.$refs.scrollContent.clientHeight
238
+ const currentWrapperHeight = this.$parent.$refs.movableArea.clientHeight
239
+
240
+ const heightChanged =
241
+ currentContentHeight !== this.cachedContentHeight ||
242
+ currentWrapperHeight !== this.cachedWrapperHeight
243
+
244
+ // 更新缓存的高度
245
+ this.cachedContentHeight = currentContentHeight
246
+ this.cachedWrapperHeight = currentWrapperHeight
247
+
248
+ return heightChanged
249
+ },
250
+ // 检查宽度是否发生变化
251
+ checkWidthChange () {
252
+ if (!this.$refs.scrollContent || !this.$parent.$refs.movableArea) {
253
+ return false
254
+ }
255
+
256
+ const currentContentWidth = this.$refs.scrollContent.clientWidth
257
+ const currentWrapperWidth = this.$parent.$refs.movableArea.clientWidth
258
+
259
+ const widthChanged =
260
+ currentContentWidth !== this.cachedContentWidth ||
261
+ currentWrapperWidth !== this.cachedWrapperWidth
262
+
263
+ // 更新缓存的宽度
264
+ this.cachedContentWidth = currentContentWidth
265
+ this.cachedWrapperWidth = currentWrapperWidth
266
+
267
+ return widthChanged
268
+ },
188
269
  destroyBs () {
189
270
  if (!this.bs) return
190
271
  this.bs.destroy()
@@ -364,6 +445,15 @@ export default {
364
445
  }
365
446
  extend(this.bsOptions, this.scrollOptions)
366
447
  },
448
+ // 初始化尺寸缓存
449
+ initSizeCache () {
450
+ if (this.$refs.scrollContent && this.$parent.$refs.movableArea) {
451
+ this.cachedContentHeight = this.$refs.scrollContent.clientHeight
452
+ this.cachedWrapperHeight = this.$parent.$refs.movableArea.clientHeight
453
+ this.cachedContentWidth = this.$refs.scrollContent.clientWidth
454
+ this.cachedWrapperWidth = this.$parent.$refs.movableArea.clientWidth
455
+ }
456
+ },
367
457
  // 处理小数点,四舍五入,默认保留一位小数
368
458
  roundFun (value, n = 1) {
369
459
  return Math.round(value * Math.pow(10, n)) / Math.pow(10, n)
@@ -256,8 +256,7 @@
256
256
  }
257
257
  this.initBs()
258
258
  })
259
- const elementToObserve = document.querySelector('.mpx-swiper');
260
- this.resizeObserver.observe(elementToObserve);
259
+ this.resizeObserver.observe(this.$refs.wrapper);
261
260
  }
262
261
  },
263
262
  refresh () {
@@ -124,7 +124,7 @@ export default {
124
124
  case 'postMessage':
125
125
  let data = {
126
126
  type: 'message',
127
- data: params[0]?.data
127
+ data: params[0]?.data || params[0] // 补充兜底逻辑
128
128
  }
129
129
  this.$emit(eventMessage, getCustomEvent(eventMessage, data, this))
130
130
  asyncCallback = Promise.resolve({
@@ -148,7 +148,7 @@ export default {
148
148
  break
149
149
  default:
150
150
  if (type) {
151
- const implement = mpx.config.webviewConfig.apiImplementations && mpx.config.webviewConfig.apiImplementations[type]
151
+ const implement = mpx.config.webConfig?.webviewConfig?.apiImplementations?.[type]
152
152
  if (isFunction(implement)) {
153
153
  asyncCallback = Promise.resolve(implement(...params))
154
154
  } else {
@@ -174,7 +174,7 @@ export default {
174
174
  })
175
175
  },
176
176
  hostValidate (host) {
177
- const hostWhitelists = mpx.config.webviewConfig && mpx.config.webviewConfig.hostWhitelists || []
177
+ const hostWhitelists = mpx.config.webConfig?.webviewConfig?.hostWhitelists || []
178
178
  if (hostWhitelists.length) {
179
179
  return hostWhitelists.some((item) => {
180
180
  return host.endsWith(item)
@@ -1333,8 +1333,35 @@ function processEventReact (el, options) {
1333
1333
  // }
1334
1334
  }
1335
1335
 
1336
+ function isNeedBind (configs, isProxy) {
1337
+ if (isProxy) return true
1338
+ if (configs.length > 1) return true
1339
+ if (configs.length === 1) return configs[0].hasArgs
1340
+ return false
1341
+ }
1342
+
1343
+ function processEventBinding (el, configs) {
1344
+ let resultName
1345
+ configs.forEach(({ name }) => {
1346
+ if (name) {
1347
+ // 清空原始事件绑定
1348
+ let has
1349
+ do {
1350
+ has = getAndRemoveAttr(el, name).has
1351
+ } while (has)
1352
+
1353
+ if (!resultName) {
1354
+ // 清除修饰符
1355
+ resultName = name.replace(/\..*/, '')
1356
+ }
1357
+ }
1358
+ })
1359
+ return { resultName }
1360
+ }
1361
+
1336
1362
  function processEvent (el, options) {
1337
1363
  const eventConfigMap = {}
1364
+ const finalEventsMap = {}
1338
1365
  el.attrsList.forEach(function ({ name, value }) {
1339
1366
  const parsedEvent = config[mode].event.parseEvent(name)
1340
1367
 
@@ -1346,12 +1373,15 @@ function processEvent (el, options) {
1346
1373
  const extraStr = runtimeCompile && prefix === 'catch' ? `, "__mpx_${prefix}"` : ''
1347
1374
  const parsedFunc = parseFuncStr(value, extraStr)
1348
1375
  if (parsedFunc) {
1376
+ const isCapture = /^capture/.test(prefix)
1349
1377
  if (!eventConfigMap[type]) {
1350
1378
  eventConfigMap[type] = {
1351
- configs: []
1379
+ configs: [],
1380
+ captureConfigs: []
1352
1381
  }
1353
1382
  }
1354
- eventConfigMap[type].configs.push(Object.assign({ name }, parsedFunc))
1383
+ const targetConfigs = isCapture ? eventConfigMap[type].captureConfigs : eventConfigMap[type].configs
1384
+ targetConfigs.push(Object.assign({ name }, parsedFunc))
1355
1385
  if (modifiers.indexOf('proxy') > -1 || options.forceProxyEvent) {
1356
1386
  eventConfigMap[type].proxy = true
1357
1387
  }
@@ -1393,57 +1423,57 @@ function processEvent (el, options) {
1393
1423
  }
1394
1424
 
1395
1425
  for (const type in eventConfigMap) {
1396
- let needBind = false
1397
- const { configs, proxy } = eventConfigMap[type]
1398
- delete eventConfigMap[type]
1399
- if (proxy) {
1400
- needBind = true
1401
- } else if (configs.length > 1) {
1402
- needBind = true
1403
- } else if (configs.length === 1) {
1404
- needBind = !!configs[0].hasArgs
1405
- }
1426
+ const { configs = [], captureConfigs = [], proxy } = eventConfigMap[type]
1427
+
1428
+ let needBubblingBind = isNeedBind(configs, proxy)
1429
+ let needCaptureBind = isNeedBind(captureConfigs, proxy)
1406
1430
 
1407
1431
  const escapedType = dash2hump(type)
1408
1432
  // 排除特殊情况
1409
1433
  if (!isValidIdentifierStr(escapedType)) {
1410
1434
  warn$1(`EventName ${type} which need be framework proxy processed must be a valid identifier!`)
1411
- needBind = false
1435
+ needBubblingBind = false
1436
+ needCaptureBind = false
1412
1437
  }
1413
1438
 
1414
- if (needBind) {
1415
- let resultName
1416
- configs.forEach(({ name }) => {
1417
- if (name) {
1418
- // 清空原始事件绑定
1419
- let has
1420
- do {
1421
- has = getAndRemoveAttr(el, name).has
1422
- } while (has)
1439
+ if (needBubblingBind) {
1440
+ const { resultName } = processEventBinding(el, configs)
1423
1441
 
1424
- if (!resultName) {
1425
- // 清除修饰符
1426
- resultName = name.replace(/\..*/, '')
1427
- }
1442
+ addAttrs(el, [
1443
+ {
1444
+ name: resultName || config[mode].event.getEvent(type),
1445
+ value: '__invoke'
1428
1446
  }
1447
+ ])
1448
+ if (!finalEventsMap.bubble) {
1449
+ finalEventsMap.bubble = {}
1450
+ }
1451
+ finalEventsMap.bubble[escapedType] = configs.map((item) => {
1452
+ return item.expStr
1429
1453
  })
1454
+ }
1430
1455
 
1456
+ if (needCaptureBind) {
1457
+ const { resultName } = processEventBinding(el, captureConfigs)
1431
1458
  addAttrs(el, [
1432
1459
  {
1433
1460
  name: resultName || config[mode].event.getEvent(type),
1434
- value: '__invoke'
1461
+ value: '__captureInvoke'
1435
1462
  }
1436
1463
  ])
1437
- eventConfigMap[escapedType] = configs.map((item) => {
1464
+ if (!finalEventsMap.capture) {
1465
+ finalEventsMap.capture = {}
1466
+ }
1467
+ finalEventsMap.capture[escapedType] = captureConfigs.map((item) => {
1438
1468
  return item.expStr
1439
1469
  })
1440
1470
  }
1441
1471
  }
1442
1472
 
1443
- if (!isEmptyObject(eventConfigMap)) {
1473
+ if (!isEmptyObject(finalEventsMap)) {
1444
1474
  addAttrs(el, [{
1445
1475
  name: 'data-eventconfigs',
1446
- value: `{{${shallowStringify(eventConfigMap, true)}}}`
1476
+ value: `{{${shallowStringify(finalEventsMap, true)}}}`
1447
1477
  }])
1448
1478
  }
1449
1479
  }
@@ -2737,8 +2767,8 @@ function processElement (el, root, options, meta) {
2737
2767
  processIf(el)
2738
2768
  processFor(el)
2739
2769
  processRefReact(el, meta)
2770
+ processStyleReact(el, options)
2740
2771
  if (!pass) {
2741
- processStyleReact(el, options)
2742
2772
  processEventReact(el, options)
2743
2773
  processComponentGenerics(el, meta)
2744
2774
  processComponentIs(el, options)
package/lib/wxss/utils.js CHANGED
@@ -1052,7 +1052,7 @@ function getModuleCode (
1052
1052
  `@import url(${url});`
1053
1053
  )}${printedParam.length > 0 ? `, ${printedParam}` : ''}]);\n`
1054
1054
  } else {
1055
- // 符合css后缀名的文件经过mpx处理后会带上相应的后缀防止使用 WebPack 的默认解析规则,此时 require/import 相应路径时,导出的不是一段 css 代码了,事实上是一个文件路径。
1055
+ // 符合css后缀名的文件经过mpx处理后会带上相应的后缀防止使用 webpack 的默认解析规则,此时 require/import 相应路径时,导出的不是一段 css 代码了,事实上是一个文件路径。
1056
1056
  const printedParam = printParams(media, dedupe, supports, layer)
1057
1057
  const otherParams = printedParam.length > 0 ? printedParam : ''
1058
1058
  beforeCode += `___CSS_LOADER_EXPORT___.push([module.id, '@import "' + ${item.importName} + '";', ${JSON.stringify(otherParams)} ]);\n`