@mpxjs/webpack-plugin 2.10.6-beta.2 → 2.10.6-beta.4
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.
- package/lib/file-loader.js +1 -1
- package/lib/index.js +35 -14
- package/lib/platform/index.js +2 -4
- package/lib/platform/json/wx/index.js +43 -25
- package/lib/platform/template/wx/component-config/fix-component-name.js +2 -2
- package/lib/platform/template/wx/component-config/index.js +2 -2
- package/lib/platform/template/wx/component-config/template.js +1 -26
- package/lib/platform/template/wx/index.js +5 -11
- package/lib/react/LoadAsyncChunkModule.js +68 -0
- package/lib/react/index.js +3 -1
- package/lib/react/processJSON.js +72 -17
- package/lib/react/processScript.js +4 -3
- package/lib/react/script-helper.js +92 -18
- package/lib/runtime/components/react/AsyncContainer.tsx +217 -0
- package/lib/runtime/components/react/AsyncSuspense.tsx +81 -0
- package/lib/runtime/components/react/dist/AsyncContainer.jsx +160 -0
- package/lib/runtime/components/react/dist/AsyncSuspense.jsx +68 -0
- package/lib/runtime/components/react/dist/getInnerListeners.js +1 -1
- package/lib/runtime/components/react/dist/mpx-input.jsx +1 -1
- package/lib/runtime/components/react/dist/mpx-movable-view.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-swiper-item.jsx +2 -2
- package/lib/runtime/components/react/dist/mpx-swiper.jsx +53 -27
- package/lib/runtime/components/react/dist/mpx-web-view.jsx +14 -28
- package/lib/runtime/components/react/dist/useAnimationHooks.js +2 -87
- package/lib/runtime/components/react/dist/utils.jsx +84 -0
- package/lib/runtime/components/react/getInnerListeners.ts +1 -1
- package/lib/runtime/components/react/mpx-input.tsx +1 -1
- package/lib/runtime/components/react/mpx-movable-view.tsx +2 -2
- package/lib/runtime/components/react/mpx-swiper-item.tsx +2 -2
- package/lib/runtime/components/react/mpx-swiper.tsx +53 -25
- package/lib/runtime/components/react/mpx-web-view.tsx +13 -33
- package/lib/runtime/components/react/types/global.d.ts +15 -0
- package/lib/runtime/components/react/useAnimationHooks.ts +2 -85
- package/lib/runtime/components/react/utils.tsx +83 -1
- package/lib/runtime/optionProcessor.js +2 -2
- package/lib/template-compiler/compiler.js +11 -61
- package/lib/utils/dom-tag-config.js +17 -3
- package/lib/web/index.js +0 -2
- package/lib/web/processScript.js +7 -29
- package/lib/web/processTemplate.js +4 -10
- package/lib/web/script-helper.js +1 -1
- package/package.json +1 -1
- package/lib/dependencies/WriteVfsDependency.js +0 -46
- package/lib/utils/get-template-content.js +0 -47
- package/lib/web/template2vue.js +0 -280
- package/lib/web/wxml-template-loader.js +0 -29
|
@@ -23,6 +23,7 @@ import Portal from './mpx-portal'
|
|
|
23
23
|
* ✔ easing-function ="easeOutCubic"
|
|
24
24
|
* ✘ display-multiple-items
|
|
25
25
|
* ✘ snap-to-edge
|
|
26
|
+
* ✔ disableGesture
|
|
26
27
|
*/
|
|
27
28
|
type EaseType = 'default' | 'linear' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic'
|
|
28
29
|
type StrAbsoType = 'absoluteX' | 'absoluteY'
|
|
@@ -206,6 +207,10 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
206
207
|
const moveTranstion = useSharedValue(0)
|
|
207
208
|
// 记录从onBegin 到 onTouchesUp 的时间
|
|
208
209
|
const moveTime = useSharedValue(0)
|
|
210
|
+
// 记录从onBegin 到 onTouchesCancelled 另外一个方向移动的距离
|
|
211
|
+
const anotherDirectionMove = useSharedValue(0)
|
|
212
|
+
// 另一个方向的
|
|
213
|
+
const anotherAbso = 'absolute' + (dir === 'x' ? 'y' : 'x').toUpperCase() as StrAbsoType
|
|
209
214
|
const timerId = useRef(0 as number | ReturnType<typeof setTimeout>)
|
|
210
215
|
const intervalTimer = props.interval || 500
|
|
211
216
|
|
|
@@ -504,7 +509,11 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
504
509
|
}, [children.length])
|
|
505
510
|
|
|
506
511
|
useEffect(() => {
|
|
507
|
-
|
|
512
|
+
// 1. 如果用户在touch的过程中, 外部更新了current以外部为准(小程序表现)
|
|
513
|
+
// 2. 手指滑动过程中更新索引,外部会把current再穿进来,导致offset直接更新了
|
|
514
|
+
if (props.current !== currentIndex.value) {
|
|
515
|
+
updateCurrent(props.current || 0, step.value)
|
|
516
|
+
}
|
|
508
517
|
}, [props.current])
|
|
509
518
|
|
|
510
519
|
useEffect(() => {
|
|
@@ -566,18 +575,25 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
566
575
|
targetOffset: -moveToTargetPos
|
|
567
576
|
}
|
|
568
577
|
}
|
|
569
|
-
function
|
|
578
|
+
function checkUnCircular (eventData: EventDataType) {
|
|
570
579
|
'worklet'
|
|
571
580
|
const { translation } = eventData
|
|
572
581
|
const currentOffset = Math.abs(offset.value)
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
582
|
+
// 向右滑动swiper
|
|
583
|
+
if (translation < 0) {
|
|
584
|
+
const boundaryOffset = step.value * (childrenLength.value - 1)
|
|
585
|
+
const gestureMovePos = Math.abs(translation) + currentOffset
|
|
586
|
+
return {
|
|
587
|
+
// 防止快速连续向右滑动时,手势移动的距离 加 当前的offset超出边界
|
|
588
|
+
targetOffset: gestureMovePos > boundaryOffset ? -boundaryOffset : offset.value + translation,
|
|
589
|
+
canMove: currentOffset < boundaryOffset
|
|
578
590
|
}
|
|
579
591
|
} else {
|
|
580
|
-
|
|
592
|
+
const gestureMovePos = currentOffset - translation
|
|
593
|
+
return {
|
|
594
|
+
targetOffset: gestureMovePos < 0 ? 0 : offset.value + translation,
|
|
595
|
+
canMove: currentOffset > 0
|
|
596
|
+
}
|
|
581
597
|
}
|
|
582
598
|
}
|
|
583
599
|
function handleEnd (eventData: EventDataType) {
|
|
@@ -636,7 +652,7 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
636
652
|
}
|
|
637
653
|
})
|
|
638
654
|
}
|
|
639
|
-
function
|
|
655
|
+
function computeHalf () {
|
|
640
656
|
'worklet'
|
|
641
657
|
const currentOffset = Math.abs(offset.value)
|
|
642
658
|
let preOffset = (currentIndex.value + patchElmNumShared.value) * step.value
|
|
@@ -646,6 +662,14 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
646
662
|
// 正常事件中拿到的transition值(正向滑动<0,倒着滑>0)
|
|
647
663
|
const diffOffset = preOffset - currentOffset
|
|
648
664
|
const half = Math.abs(diffOffset) > step.value / 2
|
|
665
|
+
return {
|
|
666
|
+
diffOffset,
|
|
667
|
+
half
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
function handleLongPress () {
|
|
671
|
+
'worklet'
|
|
672
|
+
const { diffOffset, half } = computeHalf()
|
|
649
673
|
if (+diffOffset === 0) {
|
|
650
674
|
runOnJS(resumeLoop)()
|
|
651
675
|
} else if (half) {
|
|
@@ -701,18 +725,29 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
701
725
|
runOnJS(pauseLoop)()
|
|
702
726
|
preAbsolutePos.value = e[strAbso]
|
|
703
727
|
moveTranstion.value = e[strAbso]
|
|
728
|
+
anotherDirectionMove.value = e[anotherAbso]
|
|
704
729
|
moveTime.value = new Date().getTime()
|
|
705
730
|
})
|
|
706
|
-
.
|
|
731
|
+
.onUpdate((e) => {
|
|
707
732
|
'worklet'
|
|
708
733
|
if (touchfinish.value) return
|
|
709
|
-
const
|
|
710
|
-
const moveDistance = touchEventData[strAbso] - preAbsolutePos.value
|
|
734
|
+
const moveDistance = e[strAbso] - preAbsolutePos.value
|
|
711
735
|
const eventData = {
|
|
712
736
|
translation: moveDistance
|
|
713
737
|
}
|
|
714
|
-
//
|
|
715
|
-
|
|
738
|
+
// 1. 在Move过程中,如果手指一直没抬起来,超过一半的话也会更新索引
|
|
739
|
+
const { half } = computeHalf()
|
|
740
|
+
if (half) {
|
|
741
|
+
const { selectedIndex } = getTargetPosition(eventData)
|
|
742
|
+
currentIndex.value = selectedIndex
|
|
743
|
+
}
|
|
744
|
+
// 2. 处理用户一直拖拽到临界点的场景, 不会执行onEnd
|
|
745
|
+
const { canMove, targetOffset } = checkUnCircular(eventData)
|
|
746
|
+
if (!circularShared.value) {
|
|
747
|
+
if (canMove) {
|
|
748
|
+
offset.value = targetOffset
|
|
749
|
+
preAbsolutePos.value = e[strAbso]
|
|
750
|
+
}
|
|
716
751
|
return
|
|
717
752
|
}
|
|
718
753
|
const { isBoundary, resetOffset } = reachBoundary(eventData)
|
|
@@ -721,28 +756,21 @@ const SwiperWrapper = forwardRef<HandlerRef<View, SwiperProps>, SwiperProps>((pr
|
|
|
721
756
|
} else {
|
|
722
757
|
offset.value = moveDistance + offset.value
|
|
723
758
|
}
|
|
724
|
-
preAbsolutePos.value =
|
|
759
|
+
preAbsolutePos.value = e[strAbso]
|
|
725
760
|
})
|
|
726
|
-
.
|
|
761
|
+
.onFinalize((e) => {
|
|
727
762
|
'worklet'
|
|
728
763
|
if (touchfinish.value) return
|
|
729
|
-
const
|
|
730
|
-
const moveDistance = touchEventData[strAbso] - moveTranstion.value
|
|
764
|
+
const moveDistance = e[strAbso] - moveTranstion.value
|
|
731
765
|
touchfinish.value = true
|
|
732
766
|
const eventData = {
|
|
733
767
|
translation: moveDistance
|
|
734
768
|
}
|
|
735
|
-
if (childrenLength.value === 1) {
|
|
736
|
-
return handleBackInit()
|
|
737
|
-
}
|
|
738
|
-
// 用户手指按下起来, 需要计算正确的位置, 比如在滑动过程中突然按下然后起来,需要计算到正确的位置
|
|
739
|
-
if (!circularShared.value && !canMove(eventData)) {
|
|
740
|
-
return
|
|
741
|
-
}
|
|
742
769
|
const strVelocity = moveDistance / (new Date().getTime() - moveTime.value) * 1000
|
|
743
770
|
if (Math.abs(strVelocity) < longPressRatio) {
|
|
744
771
|
handleLongPress()
|
|
745
772
|
} else {
|
|
773
|
+
// 如果触发了onTouchesCancelled,不会触发onUpdate不会更新offset值, 索引不会变更
|
|
746
774
|
handleEnd(eventData)
|
|
747
775
|
}
|
|
748
776
|
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { forwardRef, useRef, useContext, useMemo, useState
|
|
1
|
+
import { forwardRef, useRef, useContext, useMemo, useState } from 'react'
|
|
2
2
|
import { warn, isFunction } from '@mpxjs/utils'
|
|
3
3
|
import Portal from './mpx-portal/index'
|
|
4
|
+
import { usePreventRemove, PreventRemoveEvent } from '@react-navigation/native'
|
|
4
5
|
import { getCustomEvent } from './getInnerListeners'
|
|
5
6
|
import { promisify, redirectTo, navigateTo, navigateBack, reLaunch, switchTab } from '@mpxjs/api-proxy'
|
|
6
7
|
import { WebView } from 'react-native-webview'
|
|
@@ -75,7 +76,6 @@ const styles = StyleSheet.create({
|
|
|
75
76
|
borderRadius: 10
|
|
76
77
|
}
|
|
77
78
|
})
|
|
78
|
-
|
|
79
79
|
const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((props, ref): JSX.Element | null => {
|
|
80
80
|
const { src, bindmessage, bindload, binderror } = props
|
|
81
81
|
const mpx = global.__mpx
|
|
@@ -100,8 +100,8 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
100
100
|
const webViewRef = useRef<WebView>(null)
|
|
101
101
|
const fristLoaded = useRef<boolean>(false)
|
|
102
102
|
const isLoadError = useRef<boolean>(false)
|
|
103
|
+
const isNavigateBack = useRef<boolean>(false)
|
|
103
104
|
const statusCode = useRef<string|number>('')
|
|
104
|
-
const [isLoaded, setIsLoaded] = useState<boolean>(true)
|
|
105
105
|
const defaultWebViewStyle = {
|
|
106
106
|
position: 'absolute' as const,
|
|
107
107
|
left: 0,
|
|
@@ -109,30 +109,18 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
109
109
|
top: 0,
|
|
110
110
|
bottom: 0
|
|
111
111
|
}
|
|
112
|
-
const canGoBack = useRef<boolean>(false)
|
|
113
|
-
const isNavigateBack = useRef<boolean>(false)
|
|
114
112
|
|
|
115
|
-
const
|
|
116
|
-
|
|
113
|
+
const navigation = useNavigation()
|
|
114
|
+
const [isIntercept, setIsIntercept] = useState<boolean>(false)
|
|
115
|
+
usePreventRemove(isIntercept, (event: PreventRemoveEvent) => {
|
|
116
|
+
const { data } = event
|
|
117
|
+
if (isNavigateBack.current) {
|
|
118
|
+
navigation?.dispatch(data.action)
|
|
119
|
+
} else {
|
|
117
120
|
webViewRef.current?.goBack()
|
|
118
|
-
e.preventDefault()
|
|
119
121
|
}
|
|
120
122
|
isNavigateBack.current = false
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const navigation = useNavigation()
|
|
124
|
-
|
|
125
|
-
// useEffect(() => {
|
|
126
|
-
// let beforeRemoveSubscription:any
|
|
127
|
-
// if (__mpx_mode__ !== 'ios') {
|
|
128
|
-
// beforeRemoveSubscription = navigation?.addListener?.('beforeRemove', beforeRemoveHandle)
|
|
129
|
-
// }
|
|
130
|
-
// return () => {
|
|
131
|
-
// if (isFunction(beforeRemoveSubscription)) {
|
|
132
|
-
// beforeRemoveSubscription()
|
|
133
|
-
// }
|
|
134
|
-
// }
|
|
135
|
-
// }, [])
|
|
123
|
+
})
|
|
136
124
|
|
|
137
125
|
useNodesRef<WebView, WebViewProps>(props, ref, webViewRef, {
|
|
138
126
|
style: defaultWebViewStyle
|
|
@@ -183,14 +171,14 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
183
171
|
}
|
|
184
172
|
const _changeUrl = function (navState: WebViewNavigation) {
|
|
185
173
|
if (navState.navigationType) { // navigationType这个事件在页面开始加载时和页面加载完成时都会被触发所以判断这个避免其他无效触发执行该逻辑
|
|
186
|
-
canGoBack.current = navState.canGoBack
|
|
187
174
|
currentPage.__webViewUrl = navState.url
|
|
175
|
+
setIsIntercept(navState.canGoBack)
|
|
188
176
|
}
|
|
189
177
|
}
|
|
190
178
|
|
|
191
179
|
const _onLoadProgress = function (event: WebViewProgressEvent) {
|
|
192
180
|
if (__mpx_mode__ !== 'ios') {
|
|
193
|
-
|
|
181
|
+
setIsIntercept(event.nativeEvent.canGoBack)
|
|
194
182
|
}
|
|
195
183
|
}
|
|
196
184
|
const _message = function (res: WebViewMessageEvent) {
|
|
@@ -279,7 +267,6 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
279
267
|
}
|
|
280
268
|
const onLoadEndHandle = function (res: WebViewEvent) {
|
|
281
269
|
fristLoaded.current = true
|
|
282
|
-
setIsLoaded(true)
|
|
283
270
|
const src = res.nativeEvent?.url
|
|
284
271
|
if (isLoadError.current) {
|
|
285
272
|
isLoadError.current = false
|
|
@@ -325,11 +312,6 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
325
312
|
setPageLoadErr(true)
|
|
326
313
|
}
|
|
327
314
|
}
|
|
328
|
-
const onLoadStart = function () {
|
|
329
|
-
if (!fristLoaded.current) {
|
|
330
|
-
setIsLoaded(false)
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
315
|
|
|
334
316
|
return (
|
|
335
317
|
<Portal>
|
|
@@ -342,7 +324,6 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
342
324
|
)
|
|
343
325
|
: (<WebView
|
|
344
326
|
style={ defaultWebViewStyle }
|
|
345
|
-
pointerEvents={ isLoaded ? 'auto' : 'none' }
|
|
346
327
|
source={{ uri: src }}
|
|
347
328
|
ref={webViewRef}
|
|
348
329
|
javaScriptEnabled={true}
|
|
@@ -353,7 +334,6 @@ const _WebView = forwardRef<HandlerRef<WebView, WebViewProps>, WebViewProps>((pr
|
|
|
353
334
|
onLoadEnd={onLoadEnd}
|
|
354
335
|
onHttpError={onHttpError}
|
|
355
336
|
onError={onError}
|
|
356
|
-
onLoadStart={onLoadStart}
|
|
357
337
|
allowsBackForwardNavigationGestures={true}
|
|
358
338
|
></WebView>)}
|
|
359
339
|
</Portal>
|
|
@@ -42,6 +42,21 @@ declare let global: {
|
|
|
42
42
|
|
|
43
43
|
declare module '@react-navigation/native' {
|
|
44
44
|
export function useNavigation (): Record<string, any>
|
|
45
|
+
export function usePreventRemove(
|
|
46
|
+
enabled: boolean,
|
|
47
|
+
callback: (e: { data: { action: any } }) => void
|
|
48
|
+
): void;
|
|
49
|
+
export interface PreventRemoveEvent {
|
|
50
|
+
data: {
|
|
51
|
+
action: NavigationAction;
|
|
52
|
+
route: {
|
|
53
|
+
key: string;
|
|
54
|
+
name: string;
|
|
55
|
+
params?: unknown;
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
preventDefault(): void;
|
|
59
|
+
}
|
|
45
60
|
}
|
|
46
61
|
|
|
47
62
|
declare module '*.png'
|
|
@@ -84,88 +84,6 @@ const InitialValue: ExtendedViewStyle = Object.assign({
|
|
|
84
84
|
const TransformOrigin = 'transformOrigin'
|
|
85
85
|
// transform
|
|
86
86
|
const isTransform = (key: string) => Object.keys(TransformInitial).includes(key)
|
|
87
|
-
// 多value解析
|
|
88
|
-
const parseValues = (str: string, char = ' ') => {
|
|
89
|
-
let stack = 0
|
|
90
|
-
let temp = ''
|
|
91
|
-
const result = []
|
|
92
|
-
for (let i = 0; i < str.length; i++) {
|
|
93
|
-
if (str[i] === '(') {
|
|
94
|
-
stack++
|
|
95
|
-
} else if (str[i] === ')') {
|
|
96
|
-
stack--
|
|
97
|
-
}
|
|
98
|
-
// 非括号内 或者 非分隔字符且非空
|
|
99
|
-
if (stack !== 0 || (str[i] !== char && str[i] !== ' ')) {
|
|
100
|
-
temp += str[i]
|
|
101
|
-
}
|
|
102
|
-
if ((stack === 0 && str[i] === char) || i === str.length - 1) {
|
|
103
|
-
result.push(temp)
|
|
104
|
-
temp = ''
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return result
|
|
108
|
-
}
|
|
109
|
-
// parse string transform, eg: transform: 'rotateX(45deg) rotateZ(0.785398rad)'
|
|
110
|
-
const parseTransform = (transformStr: string) => {
|
|
111
|
-
const values = parseValues(transformStr)
|
|
112
|
-
const transform: {[propName: string]: string|number|number[]}[] = []
|
|
113
|
-
values.forEach(item => {
|
|
114
|
-
const match = item.match(/([/\w]+)\((.+)\)/)
|
|
115
|
-
if (match && match.length >= 3) {
|
|
116
|
-
let key = match[1]
|
|
117
|
-
const val = match[2]
|
|
118
|
-
switch (key) {
|
|
119
|
-
case 'translateX':
|
|
120
|
-
case 'translateY':
|
|
121
|
-
case 'scaleX':
|
|
122
|
-
case 'scaleY':
|
|
123
|
-
case 'rotateX':
|
|
124
|
-
case 'rotateY':
|
|
125
|
-
case 'rotateZ':
|
|
126
|
-
case 'rotate':
|
|
127
|
-
case 'skewX':
|
|
128
|
-
case 'skewY':
|
|
129
|
-
case 'perspective':
|
|
130
|
-
// rotate 处理成 rotateZ
|
|
131
|
-
key = key === 'rotate' ? 'rotateZ' : key
|
|
132
|
-
// 单个值处理
|
|
133
|
-
transform.push({ [key]: global.__formatValue(val) })
|
|
134
|
-
break
|
|
135
|
-
case 'matrix':
|
|
136
|
-
transform.push({ [key]: parseValues(val, ',').map(val => +val) })
|
|
137
|
-
break
|
|
138
|
-
case 'translate':
|
|
139
|
-
case 'scale':
|
|
140
|
-
case 'skew':
|
|
141
|
-
case 'translate3d': // x y 支持 z不支持
|
|
142
|
-
case 'scale3d': // x y 支持 z不支持
|
|
143
|
-
{
|
|
144
|
-
// 2 个以上的值处理
|
|
145
|
-
key = key.replace('3d', '')
|
|
146
|
-
const vals = parseValues(val, ',').splice(0, 3)
|
|
147
|
-
// scale(.5) === scaleX(.5) scaleY(.5)
|
|
148
|
-
if (vals.length === 1 && key === 'scale') {
|
|
149
|
-
vals.push(vals[0])
|
|
150
|
-
}
|
|
151
|
-
const xyz = ['X', 'Y', 'Z']
|
|
152
|
-
transform.push(...vals.map((v, index) => {
|
|
153
|
-
return { [`${key}${xyz[index] || ''}`]: global.__formatValue(v.trim()) }
|
|
154
|
-
}))
|
|
155
|
-
break
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
})
|
|
160
|
-
return transform
|
|
161
|
-
}
|
|
162
|
-
// format style
|
|
163
|
-
const formatStyle = (style: ExtendedViewStyle): ExtendedViewStyle => {
|
|
164
|
-
if (!style.transform || Array.isArray(style.transform)) return style
|
|
165
|
-
return Object.assign({}, style, {
|
|
166
|
-
transform: parseTransform(style.transform)
|
|
167
|
-
})
|
|
168
|
-
}
|
|
169
87
|
|
|
170
88
|
// transform 数组转对象
|
|
171
89
|
function getTransformObj (transforms: { [propName: string]: string | number }[]) {
|
|
@@ -176,7 +94,7 @@ function getTransformObj (transforms: { [propName: string]: string | number }[])
|
|
|
176
94
|
}
|
|
177
95
|
|
|
178
96
|
export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAnimation?: boolean, layoutRef: MutableRefObject<any>, transitionend?: (event: NativeSyntheticEvent<TouchEvent> | unknown) => void }) {
|
|
179
|
-
const { style = {}, animation, enableAnimation, transitionend, layoutRef } = props
|
|
97
|
+
const { style: originalStyle = {}, animation, enableAnimation, transitionend, layoutRef } = props
|
|
180
98
|
const enableStyleAnimation = enableAnimation || !!animation
|
|
181
99
|
const enableAnimationRef = useRef(enableStyleAnimation)
|
|
182
100
|
if (enableAnimationRef.current !== enableStyleAnimation) {
|
|
@@ -185,7 +103,6 @@ export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAni
|
|
|
185
103
|
|
|
186
104
|
if (!enableAnimationRef.current) return { enableStyleAnimation: false }
|
|
187
105
|
|
|
188
|
-
const originalStyle = formatStyle(style)
|
|
189
106
|
// id 标识
|
|
190
107
|
const id = animation?.id || -1
|
|
191
108
|
// 有动画样式的 style key
|
|
@@ -214,7 +131,7 @@ export default function useAnimationHooks<T, P> (props: _ViewProps & { enableAni
|
|
|
214
131
|
useEffect(() => {
|
|
215
132
|
// style 更新后同步更新 lastStyleRef & shareValMap
|
|
216
133
|
updateStyleVal()
|
|
217
|
-
}, [
|
|
134
|
+
}, [originalStyle])
|
|
218
135
|
// ** 获取动画样式prop & 驱动动画
|
|
219
136
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
220
137
|
useEffect(() => {
|
|
@@ -285,7 +285,86 @@ function transformPosition (styleObj: Record<string, any>, meta: PositionMeta) {
|
|
|
285
285
|
meta.hasPositionFixed = true
|
|
286
286
|
}
|
|
287
287
|
}
|
|
288
|
-
|
|
288
|
+
// 多value解析
|
|
289
|
+
function parseValues (str: string, char = ' ') {
|
|
290
|
+
let stack = 0
|
|
291
|
+
let temp = ''
|
|
292
|
+
const result = []
|
|
293
|
+
for (let i = 0; i < str.length; i++) {
|
|
294
|
+
if (str[i] === '(') {
|
|
295
|
+
stack++
|
|
296
|
+
} else if (str[i] === ')') {
|
|
297
|
+
stack--
|
|
298
|
+
}
|
|
299
|
+
// 非括号内 或者 非分隔字符且非空
|
|
300
|
+
if (stack !== 0 || (str[i] !== char && str[i] !== ' ')) {
|
|
301
|
+
temp += str[i]
|
|
302
|
+
}
|
|
303
|
+
if ((stack === 0 && str[i] === char) || i === str.length - 1) {
|
|
304
|
+
result.push(temp)
|
|
305
|
+
temp = ''
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return result
|
|
309
|
+
}
|
|
310
|
+
// parse string transform, eg: transform: 'rotateX(45deg) rotateZ(0.785398rad)'
|
|
311
|
+
function parseTransform (transformStr: string) {
|
|
312
|
+
const values = parseValues(transformStr)
|
|
313
|
+
const transform: {[propName: string]: string|number|number[]}[] = []
|
|
314
|
+
values.forEach(item => {
|
|
315
|
+
const match = item.match(/([/\w]+)\((.+)\)/)
|
|
316
|
+
if (match && match.length >= 3) {
|
|
317
|
+
let key = match[1]
|
|
318
|
+
const val = match[2]
|
|
319
|
+
switch (key) {
|
|
320
|
+
case 'translateX':
|
|
321
|
+
case 'translateY':
|
|
322
|
+
case 'scaleX':
|
|
323
|
+
case 'scaleY':
|
|
324
|
+
case 'rotateX':
|
|
325
|
+
case 'rotateY':
|
|
326
|
+
case 'rotateZ':
|
|
327
|
+
case 'rotate':
|
|
328
|
+
case 'skewX':
|
|
329
|
+
case 'skewY':
|
|
330
|
+
case 'perspective':
|
|
331
|
+
// rotate 处理成 rotateZ
|
|
332
|
+
key = key === 'rotate' ? 'rotateZ' : key
|
|
333
|
+
// 单个值处理
|
|
334
|
+
transform.push({ [key]: global.__formatValue(val) })
|
|
335
|
+
break
|
|
336
|
+
case 'matrix':
|
|
337
|
+
transform.push({ [key]: parseValues(val, ',').map(val => +val) })
|
|
338
|
+
break
|
|
339
|
+
case 'translate':
|
|
340
|
+
case 'scale':
|
|
341
|
+
case 'skew':
|
|
342
|
+
case 'translate3d': // x y 支持 z不支持
|
|
343
|
+
case 'scale3d': // x y 支持 z不支持
|
|
344
|
+
{
|
|
345
|
+
// 2 个以上的值处理
|
|
346
|
+
key = key.replace('3d', '')
|
|
347
|
+
const vals = parseValues(val, ',').splice(0, 3)
|
|
348
|
+
// scale(.5) === scaleX(.5) scaleY(.5)
|
|
349
|
+
if (vals.length === 1 && key === 'scale') {
|
|
350
|
+
vals.push(vals[0])
|
|
351
|
+
}
|
|
352
|
+
const xyz = ['X', 'Y', 'Z']
|
|
353
|
+
transform.push(...vals.map((v, index) => {
|
|
354
|
+
return { [`${key}${xyz[index] || ''}`]: global.__formatValue(v.trim()) }
|
|
355
|
+
}))
|
|
356
|
+
break
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
})
|
|
361
|
+
return transform
|
|
362
|
+
}
|
|
363
|
+
// format style transform
|
|
364
|
+
function transformTransform (style: Record<string, any>) {
|
|
365
|
+
if (!style.transform || Array.isArray(style.transform)) return
|
|
366
|
+
style.transform = parseTransform(style.transform)
|
|
367
|
+
}
|
|
289
368
|
interface TransformStyleConfig {
|
|
290
369
|
enableVar?: boolean
|
|
291
370
|
externalVarContext?: Record<string, any>
|
|
@@ -428,6 +507,9 @@ export function useTransformStyle (styleObj: Record<string, any> = {}, { enableV
|
|
|
428
507
|
// transform number enum stringify
|
|
429
508
|
transformStringify(normalStyle)
|
|
430
509
|
|
|
510
|
+
// transform 字符串格式转化数组格式
|
|
511
|
+
transformTransform(normalStyle)
|
|
512
|
+
|
|
431
513
|
return {
|
|
432
514
|
hasVarDec,
|
|
433
515
|
varContextRef,
|
|
@@ -79,7 +79,7 @@ registered in parent context!`)
|
|
|
79
79
|
transitionName: ''
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
if (!global.__mpx.config.webConfig
|
|
82
|
+
if (!global.__mpx.config.webConfig.disablePageTransition) {
|
|
83
83
|
option.watch = {
|
|
84
84
|
$route: {
|
|
85
85
|
handler () {
|
|
@@ -161,7 +161,7 @@ function createApp ({ componentsMap, Vue, pagesMap, firstPage, VueRouter, App, t
|
|
|
161
161
|
redirect: '/' + firstPage
|
|
162
162
|
})
|
|
163
163
|
}
|
|
164
|
-
const webRouteConfig = global.__mpx.config.webConfig
|
|
164
|
+
const webRouteConfig = global.__mpx.config.webConfig.routeConfig || global.__mpx.config.webRouteConfig
|
|
165
165
|
global.__mpxRouter = option.router = new VueRouter(extend({ routes }, webRouteConfig))
|
|
166
166
|
let mpxStackPath = []
|
|
167
167
|
if (isBrowser) {
|