@mpxjs/core 2.10.4-beta.1 → 2.10.4-beta.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/core",
3
- "version": "2.10.4-beta.1",
3
+ "version": "2.10.4-beta.10",
4
4
  "description": "mpx runtime core",
5
5
  "keywords": [
6
6
  "miniprogram",
@@ -4,10 +4,12 @@ import { makeMap, spreadProp, getFocusedNavigation, hasOwn } 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'
7
+ import { ref } from '../observer/ref'
8
+ import { watch } from '../observer/watch'
7
9
  import { createElement, memo, useRef, useEffect } from 'react'
8
10
  import * as ReactNative from 'react-native'
9
11
  import { initAppProvides } from './export/inject'
10
- import { NavigationContainer, createStackNavigator, SafeAreaProvider } from './env/navigationHelper'
12
+ import { NavigationContainer, createNativeStackNavigator, SafeAreaProvider } from './env/navigationHelper'
11
13
 
12
14
  const appHooksMap = makeMap(mergeLifecycle(LIFECYCLE).app)
13
15
 
@@ -52,25 +54,25 @@ export default function createApp (options) {
52
54
 
53
55
  const pages = currentInject.getPages() || {}
54
56
  const firstPage = currentInject.firstPage
55
- const Stack = createStackNavigator()
57
+ const Stack = createNativeStackNavigator()
56
58
  const getPageScreens = (initialRouteName, initialParams) => {
57
59
  return Object.entries(pages).map(([key, item]) => {
58
- const options = {
59
- // __mpxPageStatusMap 为编译注入的全局变量
60
- headerShown: !(Object.assign({}, global.__mpxPageConfig, global.__mpxPageConfigsMap[key]).navigationStyle === 'custom')
61
- }
60
+ // const options = {
61
+ // // __mpxPageStatusMap 为编译注入的全局变量
62
+ // headerShown: !(Object.assign({}, global.__mpxPageConfig, global.__mpxPageConfigsMap[key]).navigationStyle === 'custom')
63
+ // }
62
64
  if (key === initialRouteName) {
63
65
  return createElement(Stack.Screen, {
64
66
  name: key,
65
67
  component: item,
66
- initialParams,
67
- options
68
+ initialParams
69
+ // options
68
70
  })
69
71
  }
70
72
  return createElement(Stack.Screen, {
71
73
  name: key,
72
- component: item,
73
- options
74
+ component: item
75
+ // options
74
76
  })
75
77
  })
76
78
  }
@@ -90,6 +92,82 @@ export default function createApp (options) {
90
92
  global.__navigationHelper.lastFailCallback = null
91
93
  }
92
94
  }
95
+ const appState = ref('')
96
+ watch(() => appState.value, (value) => {
97
+ if (value === 'show') {
98
+ let options = global.__mpxEnterOptions || {}
99
+ const navigation = getFocusedNavigation()
100
+ if (navigation) {
101
+ const state = navigation.getState()
102
+ const current = state.routes[state.index]
103
+ options = {
104
+ path: current.name,
105
+ query: current.params,
106
+ scene: 0,
107
+ shareTicket: '',
108
+ referrerInfo: {}
109
+ }
110
+ }
111
+ global.__mpxAppCbs.show.forEach((cb) => {
112
+ cb(options)
113
+ })
114
+ } else if (value === 'hide') {
115
+ global.__mpxAppCbs.hide.forEach((cb) => {
116
+ cb({
117
+ reason: 3
118
+ })
119
+ })
120
+ }
121
+ })
122
+ const onAppStateChange = (currentState) => {
123
+ const navigation = getFocusedNavigation()
124
+ if (currentState === 'active') {
125
+ appState.value = 'show'
126
+ if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
127
+ global.__mpxPageStatusMap[navigation.pageId] = 'show'
128
+ }
129
+ } else if (currentState === 'inactive' || currentState === 'background') {
130
+ appState.value = 'hide'
131
+ if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
132
+ global.__mpxPageStatusMap[navigation.pageId] = 'hide'
133
+ }
134
+ }
135
+ }
136
+
137
+ const onAppStateChange = (currentState) => {
138
+ // 业务上配置禁止的话就不响应监听事件
139
+ if (currentState === 'active') {
140
+ let options = global.__mpxEnterOptions || {}
141
+ const navigation = getFocusedNavigation()
142
+ if (navigation) {
143
+ const state = navigation.getState()
144
+ const current = state.routes[state.index]
145
+ options = {
146
+ path: current.name,
147
+ query: current.params,
148
+ scene: 0,
149
+ shareTicket: '',
150
+ referrerInfo: {}
151
+ }
152
+ }
153
+ global.__mpxAppCbs.show.forEach((cb) => {
154
+ cb(options)
155
+ })
156
+ if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
157
+ global.__mpxPageStatusMap[navigation.pageId] = 'show'
158
+ }
159
+ } else if (currentState === 'inactive' || currentState === 'background') {
160
+ global.__mpxAppCbs.hide.forEach((cb) => {
161
+ cb({
162
+ reason: 3
163
+ })
164
+ })
165
+ const navigation = getFocusedNavigation()
166
+ if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
167
+ global.__mpxPageStatusMap[navigation.pageId] = 'hide'
168
+ }
169
+ }
170
+ }
93
171
 
94
172
  global.__mpxAppLaunched = false
95
173
  global.__mpxOptionsMap[currentInject.moduleId] = memo((props) => {
@@ -127,47 +205,17 @@ export default function createApp (options) {
127
205
  global.__mpxLaunchOptions = options
128
206
  defaultOptions.onLaunch && defaultOptions.onLaunch.call(appInstance, options)
129
207
  }
130
- global.__mpxAppCbs.show.forEach((cb) => {
131
- cb(options)
132
- })
208
+ appState.value = 'show'
133
209
  global.__mpxAppLaunched = true
134
210
  global.__mpxAppHotLaunched = true
135
211
  }
136
212
  }
137
213
 
138
214
  useEffect(() => {
139
- const changeSubscription = ReactNative.AppState.addEventListener('change', (currentState) => {
140
- if (currentState === 'active') {
141
- let options = global.__mpxEnterOptions
142
- const navigation = getFocusedNavigation()
143
- if (navigation) {
144
- const state = navigation.getState()
145
- const current = state.routes[state.index]
146
- options = {
147
- path: current.name,
148
- query: current.params,
149
- scene: 0,
150
- shareTicket: '',
151
- referrerInfo: {}
152
- }
153
- }
154
- global.__mpxAppCbs.show.forEach((cb) => {
155
- cb(options)
156
- })
157
- if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
158
- global.__mpxPageStatusMap[navigation.pageId] = 'show'
159
- }
160
- } else if (currentState === 'inactive' || currentState === 'background') {
161
- global.__mpxAppCbs.hide.forEach((cb) => {
162
- cb({
163
- reason: 3
164
- })
165
- })
166
- const navigation = getFocusedNavigation()
167
- if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
168
- global.__mpxPageStatusMap[navigation.pageId] = 'hide'
169
- }
170
- }
215
+ const changeSubscription = ReactNative.AppState.addEventListener('change', (state) => {
216
+ // 外层可能会异常设置此配置,因此加载监听函数内部
217
+ if (Mpx.config.rnConfig.disableReactNativeAppStateChange) return
218
+ onAppStateChange(state)
171
219
  })
172
220
 
173
221
  let count = 0
@@ -195,32 +243,10 @@ export default function createApp (options) {
195
243
 
196
244
  const { initialRouteName, initialParams } = initialRouteRef.current
197
245
  const navScreenOpts = {
198
- // 7.x替换headerBackTitleVisible
199
- // headerBackButtonDisplayMode: 'minimal',
200
- headerBackTitleVisible: false,
201
- headerShadowVisible: false
202
- // 整体切换native-stack时进行修改如下
203
- // statusBarTranslucent: true,
204
- // statusBarBackgroundColor: 'transparent'
205
- }
206
- if (__mpx_mode__ === 'ios') {
207
- // ios使用native-stack
208
- const headerBackImageSource = Mpx.config.rnConfig.headerBackImageSource || null
209
- if (headerBackImageSource) {
210
- navScreenOpts.headerBackImageSource = headerBackImageSource
211
- }
212
- } else {
213
- // 安卓上会出现导航条闪现的问题所以默认加headerShown false(stack版本, native-stack版本可以干掉)
214
- // iOS加上默认headerShown false的话会因为iOS根高度是screenHeight - useHeaderHeight()会导致出现渲染两次情况,因此iOS不加此默认值
215
- navScreenOpts.headerShown = false
216
- // 安卓和鸿蒙先用stack
217
- const headerBackImageProps = Mpx.config.rnConfig.headerBackImageProps || null
218
- if (headerBackImageProps) {
219
- navScreenOpts.headerBackImage = () => {
220
- return createElement(ReactNative.Image, headerBackImageProps)
221
- }
222
- }
223
- }
246
+ headerShown: false,
247
+ statusBarTranslucent: true,
248
+ statusBarBackgroundColor: 'transparent'
249
+ }
224
250
 
225
251
  return createElement(SafeAreaProvider,
226
252
  null,
@@ -256,4 +282,12 @@ export default function createApp (options) {
256
282
  global.__mpxPageStatusMap[navigation.pageId] = status
257
283
  }
258
284
  }
285
+
286
+ // 用于外层业务用来设置App的展示情况
287
+ global.setAppShow = function () {
288
+ onAppStateChange('active')
289
+ }
290
+ global.setAppHide = function () {
291
+ onAppStateChange('inactive')
292
+ }
259
293
  }
@@ -0,0 +1,108 @@
1
+ import { createElement, useState, useMemo } from 'react'
2
+ import { useSafeAreaInsets } from 'react-native-safe-area-context'
3
+ import * as ReactNative from 'react-native'
4
+ import Mpx from '../../index'
5
+
6
+ export function useInnerHeaderHeight (pageconfig) {
7
+ if (pageconfig.navigationStyle === 'custom') {
8
+ return 0
9
+ } else {
10
+ const safeAreaTop = useSafeAreaInsets()?.top || 0
11
+ const headerHeight = safeAreaTop + getTitleHeight()
12
+ return headerHeight
13
+ }
14
+ }
15
+
16
+ // 固定写死高度
17
+ function getTitleHeight () {
18
+ return 44
19
+ }
20
+
21
+ // 计算颜色亮度
22
+ const getColorBrightness = (color) => {
23
+ const processedColor = ReactNative.processColor(color)
24
+ if (typeof processedColor === 'number') {
25
+ const r = (processedColor >> 16) & 255
26
+ const g = (processedColor >> 8) & 255
27
+ const b = processedColor & 255
28
+ return (r * 299 + g * 587 + b * 114) / 1000
29
+ }
30
+ return 0
31
+ }
32
+
33
+ const styles = ReactNative.StyleSheet.create({
34
+ header: {
35
+ elevation: 3
36
+ },
37
+ headerContent: {
38
+ flexDirection: 'row',
39
+ alignItems: 'center',
40
+ justifyContent: 'center'
41
+ },
42
+ backButton: {
43
+ position: 'absolute',
44
+ height: '100%',
45
+ width: 40,
46
+ left: 0,
47
+ top: 0,
48
+ alignItems: 'center',
49
+ justifyContent: 'center'
50
+ },
51
+ backButtonImage: {
52
+ width: 22,
53
+ height: 22
54
+ },
55
+ title: {
56
+ fontSize: 17,
57
+ fontWeight: 600
58
+ }
59
+ })
60
+
61
+ export function innerNav ({ props, navigation }) {
62
+ const { pageConfig } = props
63
+ const [innerPageConfig, setPageConfig] = useState(pageConfig || {})
64
+ navigation.setPageConfig = (config) => {
65
+ const newConfig = Object.assign({}, innerPageConfig, config)
66
+ setPageConfig(newConfig)
67
+ }
68
+
69
+ const isCustom = innerPageConfig.navigationStyle === 'custom'
70
+ if (isCustom) return null
71
+ const safeAreaTop = useSafeAreaInsets()?.top || 0
72
+
73
+ // 回退按钮的颜色,根据背景色的亮度来进行调节
74
+ const backButtonColor = useMemo(() => {
75
+ return getColorBrightness(innerPageConfig.navigationBarBackgroundColor) > 128 ? '#000000' : '#ffffff'
76
+ }, [innerPageConfig.navigationBarBackgroundColor])
77
+
78
+ // 假设是栈导航,获取栈的长度
79
+ const stackLength = navigation.getState()?.routes?.length
80
+ // 用于外部注册打开RN容器之前的栈长度
81
+ const beforeStackLength = Mpx.config?.rnConfig?.beforeStackLength || 0
82
+
83
+ // 回退按钮与图标
84
+ const backElement = stackLength + beforeStackLength > 1
85
+ ? createElement(ReactNative.TouchableOpacity, {
86
+ style: [styles.backButton],
87
+ onPress: () => { navigation.goBack() }
88
+ }, createElement(ReactNative.Image, {
89
+ source: { uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAABICAYAAACqT5alAAAA2UlEQVR4nO3bMQrCUBRE0Yla6AYEN2nnBrTL+izcitW3MRDkEUWSvPzJvfCqgMwhZbAppWhNbbIHzB1g9wATERFRVyvpkj1irlpJ5X326D7WHh1hbdFD2CLpLmmftm7kfsEe09aNHFiBrT+wAlt/YAW2/sAKbP2BFdj6Ayuwy+ufz6XPL893krZ//O6iu2n4LT8kndLWTRTo4EC7BDo40C6BDg60S6CDA+0S6OBAuwQ6uNWiD2nrJmoIfU7cNWkR2hbb1UfbY7uuWhGWiIg+a/iHuHmA3QPs3gu4JW9Gan+OJAAAAABJRU5ErkJggg==' },
90
+ style: [styles.backButtonImage, { tintColor: backButtonColor }]
91
+ }))
92
+ : null
93
+
94
+ return createElement(ReactNative.View, {
95
+ style: [styles.header, {
96
+ paddingTop: safeAreaTop,
97
+ backgroundColor: innerPageConfig.navigationBarBackgroundColor || '#000000'
98
+ }]
99
+ },
100
+ createElement(ReactNative.View, {
101
+ style: styles.headerContent,
102
+ height: getTitleHeight()
103
+ }, backElement,
104
+ createElement(ReactNative.Text, {
105
+ style: [styles.title, { color: innerPageConfig.navigationBarTextStyle || 'white' }]
106
+ }, innerPageConfig.navigationBarTitleText?.trim() || ''))
107
+ )
108
+ }
@@ -1,4 +1,4 @@
1
- import { createStackNavigator } from '@react-navigation/stack'
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
4
  import { useHeaderHeight } from '@react-navigation/elements'
@@ -6,7 +6,7 @@ import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-cont
6
6
  import { GestureHandlerRootView } from 'react-native-gesture-handler'
7
7
 
8
8
  export {
9
- createStackNavigator,
9
+ createNativeStackNavigator,
10
10
  NavigationContainer,
11
11
  useHeaderHeight,
12
12
  StackActions,
@@ -1,4 +1,4 @@
1
- import { createNativeStackNavigator as createStackNavigator } from '@react-navigation/native-stack'
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
4
  import { useHeaderHeight } from '@react-navigation/elements'
@@ -6,7 +6,7 @@ import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-cont
6
6
  import { GestureHandlerRootView } from 'react-native-gesture-handler'
7
7
 
8
8
  export {
9
- createStackNavigator,
9
+ createNativeStackNavigator,
10
10
  NavigationContainer,
11
11
  useHeaderHeight,
12
12
  StackActions,
@@ -1,4 +1,4 @@
1
- import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, createElement, memo, forwardRef, useImperativeHandle, useContext, Fragment, cloneElement, createContext } from 'react'
1
+ import { useEffect, useSyncExternalStore, useRef, useMemo, createElement, memo, forwardRef, useImperativeHandle, useContext, Fragment, cloneElement, createContext } from 'react'
2
2
  import * as ReactNative from 'react-native'
3
3
  import { ReactiveEffect } from '../../observer/effect'
4
4
  import { watch } from '../../observer/watch'
@@ -15,7 +15,8 @@ import {
15
15
  KeyboardAvoidContext,
16
16
  RouteContext
17
17
  } from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/context'
18
- import { PortalHost, useSafeAreaInsets, GestureHandlerRootView, useHeaderHeight } from '../env/navigationHelper'
18
+ import { PortalHost, useSafeAreaInsets, GestureHandlerRootView } from '../env/navigationHelper'
19
+ import { innerNav, useInnerHeaderHeight } from '../env/nav'
19
20
 
20
21
  const ProviderContext = createContext(null)
21
22
  function getSystemInfo () {
@@ -51,7 +52,7 @@ function createEffect (proxy, components) {
51
52
  if (tagName === 'block') return Fragment
52
53
  const appComponents = global.__getAppComponents?.() || {}
53
54
  const generichash = proxy.target.generichash || ''
54
- const genericComponents = global.__mpxGenericsMap[generichash] || noop
55
+ const genericComponents = global.__mpxGenericsMap?.[generichash] || noop
55
56
  return components[tagName] || genericComponents(tagName) || appComponents[tagName] || getByPath(ReactNative, tagName)
56
57
  }
57
58
  const innerCreateElement = (type, ...rest) => {
@@ -445,9 +446,28 @@ const checkRelation = (options) => {
445
446
  hasAncestorRelation
446
447
  }
447
448
  }
449
+ function getLayoutData (headerHeight) {
450
+ const screenDimensions = ReactNative.Dimensions.get('screen')
451
+ const windowDimensions = ReactNative.Dimensions.get('window')
452
+ // 在横屏状态下 screen.height = window.height + bottomVirtualHeight
453
+ // 在正常状态 screen.height = window.height + bottomVirtualHeight + statusBarHeight
454
+ const isLandscape = screenDimensions.height < screenDimensions.width
455
+ const bottomVirtualHeight = isLandscape ? screenDimensions.height - windowDimensions.height : ((screenDimensions.height - windowDimensions.height - ReactNative.StatusBar.currentHeight) || 0)
456
+ return {
457
+ x: 0,
458
+ y: headerHeight,
459
+ left: 0,
460
+ top: headerHeight,
461
+ // 此处必须为windowDimensions.width,在横屏状态下windowDimensions.width才符合预期
462
+ width: windowDimensions.width,
463
+ height: screenDimensions.height - headerHeight - bottomVirtualHeight,
464
+ // ios为0 android为实际statusbar高度
465
+ statusBarHeight: ReactNative.StatusBar.currentHeight || 0,
466
+ bottomVirtualHeight: bottomVirtualHeight,
467
+ isLandscape: isLandscape
468
+ }
469
+ }
448
470
 
449
- // 临时用来存储安卓底部(iOS没有这个)的高度(虚拟按键等高度)根据第一次进入推算
450
- let bottomVirtualHeight = null
451
471
  export function PageWrapperHOC (WrappedComponent) {
452
472
  return function PageWrapperCom ({ navigation, route, pageConfig = {}, ...props }) {
453
473
  const rootRef = useRef(null)
@@ -464,59 +484,15 @@ export function PageWrapperHOC (WrappedComponent) {
464
484
  error('Using pageWrapper requires passing navigation and route')
465
485
  return null
466
486
  }
467
- usePageStatus(navigation, currentPageId)
468
- useLayoutEffect(() => {
469
- navigation.setOptions({
470
- title: currentPageConfig.navigationBarTitleText?.trim() || '',
471
- headerStyle: {
472
- backgroundColor: currentPageConfig.navigationBarBackgroundColor || '#000000'
473
- },
474
- headerTintColor: currentPageConfig.navigationBarTextStyle || 'white'
475
- })
476
-
477
- // TODO 此部分内容在native-stack可删除,用setOptions设置
478
- if (__mpx_mode__ !== 'ios') {
479
- ReactNative.StatusBar.setBarStyle(currentPageConfig.barStyle || 'dark-content')
480
- ReactNative.StatusBar.setTranslucent(true) // 控制statusbar是否占位
481
- ReactNative.StatusBar.setBackgroundColor('transparent')
482
- }
483
- }, [])
484
-
485
- const headerHeight = useHeaderHeight()
487
+ const headerHeight = useInnerHeaderHeight(currentPageConfig)
488
+ navigation.layout = getLayoutData(headerHeight)
486
489
  const onLayout = () => {
487
- const screenDimensions = ReactNative.Dimensions.get('screen')
488
- if (__mpx_mode__ === 'ios') {
489
- navigation.layout = {
490
- x: 0,
491
- y: headerHeight,
492
- width: screenDimensions.width,
493
- height: screenDimensions.height - headerHeight
494
- }
495
- } else {
496
- if (bottomVirtualHeight === null) {
497
- rootRef.current?.measureInWindow((x, y, width, height) => {
498
- // 沉浸模式的计算方式
499
- bottomVirtualHeight = screenDimensions.height - height - headerHeight
500
- // 非沉浸模式(translucent=true)计算方式, 现在默认是全用沉浸模式,所以先不算这个
501
- // bottomVirtualHeight = windowDimensions.height - height - headerHeight
502
- navigation.layout = {
503
- x: 0,
504
- y: headerHeight,
505
- width: screenDimensions.width,
506
- height: height
507
- }
508
- })
509
- } else {
510
- navigation.layout = {
511
- x: 0,
512
- y: headerHeight, // 这个y值
513
- width: screenDimensions.width,
514
- // 后续页面的layout是通过第一次路由进入时候推算出来的底部区域来推算出来的
515
- height: screenDimensions.height - bottomVirtualHeight - headerHeight
516
- }
517
- }
518
- }
490
+ // 当用户处于横屏或者竖屏状态的时候,需要进行layout修正
491
+ navigation.layout = getLayoutData(headerHeight)
519
492
  }
493
+
494
+ usePageStatus(navigation, currentPageId)
495
+
520
496
  const withKeyboardAvoidingView = (element) => {
521
497
  return createElement(KeyboardAvoidContext.Provider,
522
498
  {
@@ -535,26 +511,26 @@ export function PageWrapperHOC (WrappedComponent) {
535
511
  )
536
512
  )
537
513
  }
538
-
514
+ // android存在第一次打开insets都返回为0情况,后续会触发第二次渲染后正确
539
515
  navigation.insets = useSafeAreaInsets()
540
-
541
516
  return createElement(GestureHandlerRootView,
542
517
  {
543
- // https://github.com/software-mansion/react-native-reanimated/issues/6639 因存在此问题,iOS在页面上进行定宽来暂时规避
544
- style: __mpx_mode__ === 'ios' && currentPageConfig?.navigationStyle !== 'custom'
545
- ? {
546
- height: ReactNative.Dimensions.get('screen').height - useHeaderHeight()
547
- }
548
- : {
549
- flex: 1
550
- }
518
+ style: {
519
+ flex: 1
520
+ }
551
521
  },
522
+ createElement(innerNav, {
523
+ props: { pageConfig: currentPageConfig },
524
+ navigation
525
+ }),
552
526
  withKeyboardAvoidingView(
553
527
  createElement(ReactNative.View,
554
528
  {
555
529
  style: {
556
530
  flex: 1,
557
- backgroundColor: currentPageConfig?.backgroundColor || '#fff'
531
+ backgroundColor: currentPageConfig?.backgroundColor || '#fff',
532
+ // 解决页面内有元素定位relative left为负值的时候,回退的时候还能看到对应元素问题
533
+ overflow: 'hidden'
558
534
  },
559
535
  ref: rootRef,
560
536
  onLayout
@@ -582,7 +558,6 @@ export function PageWrapperHOC (WrappedComponent) {
582
558
  ))
583
559
  }
584
560
  }
585
-
586
561
  export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
587
562
  rawOptions = mergeOptions(rawOptions, type, false)
588
563
  const components = Object.assign({}, rawOptions.components, currentInject.getComponents())
@@ -656,8 +631,13 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
656
631
  return () => {
657
632
  proxy.unmounted()
658
633
  proxy.target.__resetInstance()
634
+ // 热更新下会销毁旧页面并创建新页面组件,且旧页面组件销毁时机晚于新页面组件创建,此时__mpxPagesMap中存储的为新页面组件,不应该删除
635
+ // 所以需要判断路由表中存储的页面实例是否为当前页面实例
659
636
  if (type === 'page') {
660
- delete global.__mpxPagesMap[props.route.key]
637
+ const routeKey = props.route.key
638
+ if (global.__mpxPagesMap[routeKey] && global.__mpxPagesMap[routeKey][0] === instance) {
639
+ delete global.__mpxPagesMap[routeKey]
640
+ }
661
641
  }
662
642
  }
663
643
  }, [])