@mpxjs/core 2.10.17 → 2.10.18-beta.1
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/@types/global.d.ts +1 -1
- package/@types/index.d.ts +3 -3
- package/package.json +3 -3
- package/src/convertor/convertor.js +3 -1
- package/src/convertor/getConvertMode.js +2 -1
- package/src/convertor/wxToKs.js +21 -0
- package/src/convertor/wxToWeb.js +8 -1
- package/src/core/proxy.js +14 -2
- package/src/helper/MpxScroll/index.js +17 -5
- package/src/platform/builtInMixins/index.js +7 -3
- package/src/platform/builtInMixins/pageStatusMixin.js +14 -2
- package/src/platform/builtInMixins/refsMixin.js +47 -46
- package/src/platform/builtInMixins/renderHelperMixin.js +40 -38
- package/src/platform/builtInMixins/styleHelperMixin.ios.js +98 -23
- package/src/platform/createApp.ios.js +6 -20
- package/src/platform/env/navigationHelper.ios.js +3 -2
- package/src/platform/patch/getDefaultOptions.ios.js +108 -59
- package/LICENSE +0 -433
- package/src/platform/patch/react/getDefaultOptions.ios.js +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import transferOptions from '../core/transferOptions'
|
|
2
2
|
import builtInKeysMap from './patch/builtInKeysMap'
|
|
3
|
-
import { makeMap, spreadProp, getFocusedNavigation, hasOwn } from '@mpxjs/utils'
|
|
3
|
+
import { makeMap, spreadProp, getFocusedNavigation, hasOwn, callWithErrorHandling } from '@mpxjs/utils'
|
|
4
4
|
import { mergeLifecycle } from '../convertor/mergeLifecycle'
|
|
5
5
|
import { LIFECYCLE } from '../platform/patch/lifecycle/index'
|
|
6
6
|
import Mpx from '../index'
|
|
@@ -14,10 +14,6 @@ import MpxNav from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-
|
|
|
14
14
|
|
|
15
15
|
const appHooksMap = makeMap(mergeLifecycle(LIFECYCLE).app)
|
|
16
16
|
|
|
17
|
-
function getPageSize (window = ReactNative.Dimensions.get('window')) {
|
|
18
|
-
return window.width + 'x' + window.height
|
|
19
|
-
}
|
|
20
|
-
|
|
21
17
|
function filterOptions (options, appData) {
|
|
22
18
|
const newOptions = {}
|
|
23
19
|
Object.keys(options).forEach(key => {
|
|
@@ -74,13 +70,12 @@ export default function createApp (options) {
|
|
|
74
70
|
)
|
|
75
71
|
}
|
|
76
72
|
const getComponent = () => {
|
|
77
|
-
return item.displayName ? item : item
|
|
73
|
+
return item.displayName ? item : callWithErrorHandling(item, null, 'require page script')
|
|
78
74
|
}
|
|
79
75
|
if (key === initialRouteName) {
|
|
80
76
|
return createElement(Stack.Screen, {
|
|
81
77
|
name: key,
|
|
82
78
|
getComponent,
|
|
83
|
-
initialParams,
|
|
84
79
|
layout: headerLayout
|
|
85
80
|
})
|
|
86
81
|
}
|
|
@@ -208,26 +203,17 @@ export default function createApp (options) {
|
|
|
208
203
|
if (Mpx.config.rnConfig.disableAppStateListener) return
|
|
209
204
|
onAppStateChange(state)
|
|
210
205
|
})
|
|
211
|
-
|
|
212
|
-
let count = 0
|
|
213
|
-
let lastPageSize = getPageSize()
|
|
214
|
-
const resizeSubScription = ReactNative.Dimensions.addEventListener('change', ({ window }) => {
|
|
215
|
-
const pageSize = getPageSize(window)
|
|
216
|
-
if (pageSize === lastPageSize) return
|
|
217
|
-
lastPageSize = pageSize
|
|
218
|
-
const navigation = getFocusedNavigation()
|
|
219
|
-
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
220
|
-
global.__mpxPageStatusMap[navigation.pageId] = `resize${count++}`
|
|
221
|
-
}
|
|
222
|
-
})
|
|
223
206
|
return () => {
|
|
224
207
|
appState.state = 'exit'
|
|
225
208
|
changeSubscription && changeSubscription.remove()
|
|
226
|
-
resizeSubScription && resizeSubScription.remove()
|
|
227
209
|
}
|
|
228
210
|
}, [])
|
|
229
211
|
|
|
230
212
|
const { initialRouteName, initialParams } = initialRouteRef.current
|
|
213
|
+
if (!global.__mpxAppHotLaunched) {
|
|
214
|
+
global.__mpxInitialRouteName = initialRouteName
|
|
215
|
+
global.__mpxInitialRunParams = initialParams
|
|
216
|
+
}
|
|
231
217
|
const navScreenOpts = {
|
|
232
218
|
headerShown: false,
|
|
233
219
|
statusBarTranslucent: Mpx.config.rnConfig.statusBarTranslucent ?? true,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createNativeStackNavigator } from '@react-navigation/native-stack'
|
|
2
2
|
import { NavigationContainer, StackActions } from '@react-navigation/native'
|
|
3
3
|
import PortalHost from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-portal/portal-host'
|
|
4
|
-
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
4
|
+
import { SafeAreaProvider, useSafeAreaInsets, initialWindowMetrics } from 'react-native-safe-area-context'
|
|
5
5
|
import { GestureHandlerRootView } from 'react-native-gesture-handler'
|
|
6
6
|
|
|
7
7
|
export {
|
|
@@ -11,5 +11,6 @@ export {
|
|
|
11
11
|
GestureHandlerRootView,
|
|
12
12
|
PortalHost,
|
|
13
13
|
SafeAreaProvider,
|
|
14
|
-
useSafeAreaInsets
|
|
14
|
+
useSafeAreaInsets,
|
|
15
|
+
initialWindowMetrics
|
|
15
16
|
}
|
|
@@ -3,25 +3,25 @@ import * as ReactNative from 'react-native'
|
|
|
3
3
|
import { ReactiveEffect } from '../../observer/effect'
|
|
4
4
|
import { watch } from '../../observer/watch'
|
|
5
5
|
import { del, reactive, set } from '../../observer/reactive'
|
|
6
|
-
import { hasOwn, isFunction, noop, isObject, isArray, getByPath, collectDataset, hump2dash, dash2hump, callWithErrorHandling, wrapMethodsWithErrorHandling, error, setFocusedNavigation } from '@mpxjs/utils'
|
|
6
|
+
import { hasOwn, isFunction, noop, isObject, isArray, getByPath, collectDataset, hump2dash, dash2hump, callWithErrorHandling, wrapMethodsWithErrorHandling, error, setFocusedNavigation, getDefaultValueByType } from '@mpxjs/utils'
|
|
7
7
|
import MpxProxy from '../../core/proxy'
|
|
8
8
|
import { BEFOREUPDATE, ONLOAD, UPDATED, ONSHOW, ONHIDE, ONRESIZE, REACTHOOKSEXEC } from '../../core/innerLifecycle'
|
|
9
9
|
import mergeOptions from '../../core/mergeOptions'
|
|
10
10
|
import { queueJob, hasPendingJob } from '../../observer/scheduler'
|
|
11
11
|
import { createSelectorQuery, createIntersectionObserver } from '@mpxjs/api-proxy'
|
|
12
|
-
import MpxKeyboardAvoidingView from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view'
|
|
13
12
|
import {
|
|
14
13
|
IntersectionObserverContext,
|
|
15
14
|
KeyboardAvoidContext,
|
|
16
15
|
ProviderContext,
|
|
17
16
|
RouteContext
|
|
18
17
|
} from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/context'
|
|
19
|
-
import { PortalHost, useSafeAreaInsets } from '../env/navigationHelper'
|
|
18
|
+
import { PortalHost, useSafeAreaInsets, initialWindowMetrics } from '../env/navigationHelper'
|
|
20
19
|
import { useInnerHeaderHeight } from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-nav'
|
|
20
|
+
import Mpx from '../../index'
|
|
21
21
|
|
|
22
22
|
function getSystemInfo () {
|
|
23
|
-
const windowDimensions =
|
|
24
|
-
const screenDimensions =
|
|
23
|
+
const windowDimensions = global.__mpxAppDimensionsInfo.window
|
|
24
|
+
const screenDimensions = global.__mpxAppDimensionsInfo.screen
|
|
25
25
|
return {
|
|
26
26
|
deviceOrientation: windowDimensions.width > windowDimensions.height ? 'landscape' : 'portrait',
|
|
27
27
|
size: {
|
|
@@ -172,8 +172,8 @@ const instanceProto = {
|
|
|
172
172
|
type: field
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
|
-
// 处理props
|
|
176
|
-
propsData[key] = field.value
|
|
175
|
+
// 处理props默认值,没有显式设置value时根据type获取默认值,与微信小程序原生行为保持一致
|
|
176
|
+
propsData[key] = hasOwn(field, 'value') ? field.value : getDefaultValueByType(field.type)
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
})
|
|
@@ -295,13 +295,18 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
|
|
|
295
295
|
instance[key] = method.bind(instance)
|
|
296
296
|
})
|
|
297
297
|
}
|
|
298
|
-
|
|
298
|
+
const loadParams = {}
|
|
299
299
|
if (type === 'page') {
|
|
300
300
|
const props = propsRef.current
|
|
301
301
|
instance.route = props.route.name
|
|
302
302
|
global.__mpxPagesMap = global.__mpxPagesMap || {}
|
|
303
303
|
global.__mpxPagesMap[props.route.key] = [instance, props.navigation]
|
|
304
304
|
setFocusedNavigation(props.navigation)
|
|
305
|
+
|
|
306
|
+
if (!global.__mpxAppHotLaunched && global.__mpxInitialRunParams) {
|
|
307
|
+
Object.assign(loadParams, global.__mpxInitialRunParams)
|
|
308
|
+
}
|
|
309
|
+
set(global.__mpxPageSizeCountMap, pageId, global.__mpxSizeCount)
|
|
305
310
|
// App onLaunch 在 Page created 之前执行
|
|
306
311
|
if (!global.__mpxAppHotLaunched && global.__mpxAppOnLaunch) {
|
|
307
312
|
global.__mpxAppOnLaunch(props.navigation)
|
|
@@ -310,17 +315,16 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
|
|
|
310
315
|
|
|
311
316
|
const proxy = instance.__mpxProxy = new MpxProxy(rawOptions, instance)
|
|
312
317
|
proxy.created()
|
|
313
|
-
|
|
314
318
|
if (type === 'page') {
|
|
315
319
|
const props = propsRef.current
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
if (isObject(
|
|
319
|
-
for (const key in
|
|
320
|
-
|
|
320
|
+
const decodedQuery = {}
|
|
321
|
+
const rawQuery = Object.assign({}, loadParams, props.route.params || {})
|
|
322
|
+
if (isObject(rawQuery)) {
|
|
323
|
+
for (const key in rawQuery) {
|
|
324
|
+
decodedQuery[key] = decodeURIComponent(rawQuery[key])
|
|
321
325
|
}
|
|
322
326
|
}
|
|
323
|
-
proxy.callHook(ONLOAD, [
|
|
327
|
+
proxy.callHook(ONLOAD, [rawQuery, decodedQuery])
|
|
324
328
|
}
|
|
325
329
|
|
|
326
330
|
Object.assign(proxy, {
|
|
@@ -375,9 +379,18 @@ const triggerPageStatusHook = (mpxProxy, event) => {
|
|
|
375
379
|
}
|
|
376
380
|
}
|
|
377
381
|
|
|
378
|
-
const triggerResizeEvent = (mpxProxy) => {
|
|
379
|
-
const
|
|
382
|
+
const triggerResizeEvent = (mpxProxy, sizeRef) => {
|
|
383
|
+
const oldSize = sizeRef.current.size
|
|
380
384
|
const systemInfo = getSystemInfo()
|
|
385
|
+
const newSize = systemInfo.size
|
|
386
|
+
|
|
387
|
+
if (oldSize && oldSize.windowWidth === newSize.windowWidth && oldSize.windowHeight === newSize.windowHeight) {
|
|
388
|
+
return
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
Object.assign(sizeRef.current, systemInfo)
|
|
392
|
+
|
|
393
|
+
const type = mpxProxy.options.__type__
|
|
381
394
|
const target = mpxProxy.target
|
|
382
395
|
mpxProxy.callHook(ONRESIZE, [systemInfo])
|
|
383
396
|
if (type === 'page') {
|
|
@@ -388,7 +401,9 @@ const triggerResizeEvent = (mpxProxy) => {
|
|
|
388
401
|
}
|
|
389
402
|
}
|
|
390
403
|
|
|
391
|
-
function usePageEffect (mpxProxy, pageId) {
|
|
404
|
+
function usePageEffect (mpxProxy, pageId, type) {
|
|
405
|
+
const sizeRef = useRef(getSystemInfo())
|
|
406
|
+
|
|
392
407
|
useEffect(() => {
|
|
393
408
|
let unWatch
|
|
394
409
|
const hasShowHook = hasPageHook(mpxProxy, [ONSHOW, 'show'])
|
|
@@ -399,21 +414,31 @@ function usePageEffect (mpxProxy, pageId) {
|
|
|
399
414
|
unWatch = watch(() => pageStatusMap[pageId], (newVal) => {
|
|
400
415
|
if (newVal === 'show' || newVal === 'hide') {
|
|
401
416
|
triggerPageStatusHook(mpxProxy, newVal)
|
|
417
|
+
// 仅在尺寸确实变化时才触发resize事件
|
|
418
|
+
triggerResizeEvent(mpxProxy, sizeRef)
|
|
419
|
+
|
|
420
|
+
// 如果当前全局size与pagesize不一致,在show之后触发一次resize事件
|
|
421
|
+
if (type === 'page' && newVal === 'show' && global.__mpxPageSizeCountMap[pageId] !== global.__mpxSizeCount) {
|
|
422
|
+
// 刷新__mpxPageSizeCountMap, 每个页面仅会执行一次,直接驱动render刷新
|
|
423
|
+
global.__mpxPageSizeCountMap[pageId] = global.__mpxSizeCount
|
|
424
|
+
}
|
|
402
425
|
} else if (/^resize/.test(newVal)) {
|
|
403
|
-
triggerResizeEvent(mpxProxy)
|
|
426
|
+
triggerResizeEvent(mpxProxy, sizeRef)
|
|
404
427
|
}
|
|
405
428
|
}, { sync: true })
|
|
406
429
|
}
|
|
407
430
|
}
|
|
408
431
|
return () => {
|
|
409
432
|
unWatch && unWatch()
|
|
433
|
+
if (type === 'page') {
|
|
434
|
+
del(global.__mpxPageSizeCountMap, pageId)
|
|
435
|
+
}
|
|
410
436
|
}
|
|
411
437
|
}, [])
|
|
412
438
|
}
|
|
413
439
|
|
|
414
440
|
let pageId = 0
|
|
415
441
|
const pageStatusMap = global.__mpxPageStatusMap = reactive({})
|
|
416
|
-
|
|
417
442
|
function usePageStatus (navigation, pageId) {
|
|
418
443
|
navigation.pageId = pageId
|
|
419
444
|
if (!hasOwn(pageStatusMap, pageId)) {
|
|
@@ -486,7 +511,17 @@ function getLayoutData (headerHeight) {
|
|
|
486
511
|
// 在横屏状态下 screen.height = window.height + bottomVirtualHeight
|
|
487
512
|
// 在正常状态 screen.height = window.height + bottomVirtualHeight + statusBarHeight
|
|
488
513
|
const isLandscape = screenDimensions.height < screenDimensions.width
|
|
489
|
-
|
|
514
|
+
let bottomVirtualHeight = 0
|
|
515
|
+
if (ReactNative.Platform.OS === 'android') {
|
|
516
|
+
if (isLandscape) {
|
|
517
|
+
bottomVirtualHeight = screenDimensions.height - windowDimensions.height
|
|
518
|
+
} else {
|
|
519
|
+
bottomVirtualHeight = initialWindowMetrics?.insets?.bottom || 0
|
|
520
|
+
if (typeof mpxGlobal.__mpx.config?.rnConfig?.getBottomVirtualHeight === 'function') {
|
|
521
|
+
bottomVirtualHeight = mpxGlobal.__mpx.config?.rnConfig?.getBottomVirtualHeight() || 0
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
490
525
|
return {
|
|
491
526
|
left: 0,
|
|
492
527
|
top: headerHeight,
|
|
@@ -519,7 +554,7 @@ export function PageWrapperHOC (WrappedComponent, pageConfig = {}) {
|
|
|
519
554
|
navigation.layout = getLayoutData(headerHeight)
|
|
520
555
|
|
|
521
556
|
useEffect(() => {
|
|
522
|
-
const dimensionListener = ReactNative.Dimensions.addEventListener('change', ({ screen }) => {
|
|
557
|
+
const dimensionListener = ReactNative.Dimensions.addEventListener('change', ({ window, screen }) => {
|
|
523
558
|
navigation.layout = getLayoutData(headerHeight)
|
|
524
559
|
})
|
|
525
560
|
return () => dimensionListener?.remove()
|
|
@@ -529,6 +564,8 @@ export function PageWrapperHOC (WrappedComponent, pageConfig = {}) {
|
|
|
529
564
|
usePageStatus(navigation, currentPageId)
|
|
530
565
|
|
|
531
566
|
const withKeyboardAvoidingView = (element) => {
|
|
567
|
+
if (currentPageConfig.disableKeyboardAvoiding) return element
|
|
568
|
+
const MpxKeyboardAvoidingView = require('@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view').default
|
|
532
569
|
return createElement(KeyboardAvoidContext.Provider,
|
|
533
570
|
{
|
|
534
571
|
value: keyboardAvoidRef
|
|
@@ -549,39 +586,53 @@ export function PageWrapperHOC (WrappedComponent, pageConfig = {}) {
|
|
|
549
586
|
// android存在第一次打开insets都返回为0情况,后续会触发第二次渲染后正确
|
|
550
587
|
navigation.insets = useSafeAreaInsets()
|
|
551
588
|
return withKeyboardAvoidingView(
|
|
552
|
-
|
|
589
|
+
createElement(ReactNative.View,
|
|
590
|
+
{
|
|
591
|
+
style: {
|
|
592
|
+
flex: 1,
|
|
593
|
+
// 页面容器背景色
|
|
594
|
+
backgroundColor: currentPageConfig?.backgroundColorContent || '#fff',
|
|
595
|
+
// 解决页面内有元素定位relative left为负值的时候,回退的时候还能看到对应元素问题
|
|
596
|
+
overflow: 'hidden'
|
|
597
|
+
}
|
|
598
|
+
},
|
|
599
|
+
createElement(RouteContext.Provider,
|
|
600
|
+
{
|
|
601
|
+
value: routeContextValRef.current
|
|
602
|
+
},
|
|
603
|
+
createElement(IntersectionObserverContext.Provider,
|
|
553
604
|
{
|
|
554
|
-
|
|
555
|
-
flex: 1,
|
|
556
|
-
// 页面容器背景色
|
|
557
|
-
backgroundColor: currentPageConfig?.backgroundColorContent || '#fff',
|
|
558
|
-
// 解决页面内有元素定位relative left为负值的时候,回退的时候还能看到对应元素问题
|
|
559
|
-
overflow: 'hidden'
|
|
560
|
-
}
|
|
605
|
+
value: intersectionObservers.current
|
|
561
606
|
},
|
|
562
|
-
createElement(
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
createElement(PortalHost,
|
|
571
|
-
null,
|
|
572
|
-
createElement(WrappedComponent, {
|
|
573
|
-
...props,
|
|
574
|
-
navigation,
|
|
575
|
-
route,
|
|
576
|
-
id: currentPageId
|
|
577
|
-
})
|
|
578
|
-
)
|
|
579
|
-
)
|
|
607
|
+
createElement(PortalHost,
|
|
608
|
+
null,
|
|
609
|
+
createElement(WrappedComponent, {
|
|
610
|
+
...props,
|
|
611
|
+
navigation,
|
|
612
|
+
route,
|
|
613
|
+
id: currentPageId
|
|
614
|
+
})
|
|
580
615
|
)
|
|
616
|
+
)
|
|
581
617
|
)
|
|
618
|
+
)
|
|
582
619
|
)
|
|
583
620
|
}
|
|
584
621
|
}
|
|
622
|
+
|
|
623
|
+
function updateProps (instance, props, validProps) {
|
|
624
|
+
Object.keys(validProps).forEach((key) => {
|
|
625
|
+
if (hasOwn(props, key)) {
|
|
626
|
+
instance[key] = props[key]
|
|
627
|
+
} else {
|
|
628
|
+
const altKey = hump2dash(key)
|
|
629
|
+
if (hasOwn(props, altKey)) {
|
|
630
|
+
instance[key] = props[altKey]
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
})
|
|
634
|
+
}
|
|
635
|
+
|
|
585
636
|
export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
586
637
|
rawOptions = mergeOptions(rawOptions, type, false)
|
|
587
638
|
const componentsMap = currentInject.componentsMap
|
|
@@ -634,16 +685,14 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
634
685
|
|
|
635
686
|
if (!isFirst) {
|
|
636
687
|
// 处理props更新
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
}
|
|
646
|
-
})
|
|
688
|
+
if (Mpx.config.forceFlushSync) {
|
|
689
|
+
// 避免开启forceFlushSync时react报错:Cannot update a component while rendering a different component
|
|
690
|
+
Promise.resolve().then(() => {
|
|
691
|
+
updateProps(instance, props, validProps)
|
|
692
|
+
})
|
|
693
|
+
} else {
|
|
694
|
+
updateProps(instance, props, validProps)
|
|
695
|
+
}
|
|
647
696
|
}
|
|
648
697
|
|
|
649
698
|
useEffect(() => {
|
|
@@ -653,7 +702,7 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
653
702
|
}
|
|
654
703
|
})
|
|
655
704
|
|
|
656
|
-
usePageEffect(proxy, pageId)
|
|
705
|
+
usePageEffect(proxy, pageId, type)
|
|
657
706
|
useEffect(() => {
|
|
658
707
|
proxy.mounted()
|
|
659
708
|
return () => {
|