@mpxjs/core 2.9.73 → 2.10.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.
@@ -1,5 +1,5 @@
1
1
  // declaration for mpx mode
2
- declare let __mpx_mode__: 'wx' | 'ali' | 'swan' | 'qq' | 'tt' | 'web' | 'dd' | 'qa' | 'jd'
2
+ declare let __mpx_mode__: 'wx' | 'ali' | 'swan' | 'qq' | 'tt' | 'web' | 'dd' | 'qa' | 'jd' | 'android' | 'ios' | 'harmony'
3
3
 
4
4
  // declaration for mpx env
5
5
  declare let __mpx_env__: string
package/@types/index.d.ts CHANGED
@@ -266,7 +266,7 @@ interface MpxConfig {
266
266
  observeClassInstance: boolean | Array<AnyConstructor>
267
267
  errorHandler: (msg: String, location: String, e: Error) => any | null
268
268
  warnHandler: (msg: String, location: String, e: Error) => any | null
269
- proxyEventHandler: (e: WechatMiniprogram.CustomEvent) => any | null
269
+ proxyEventHandler: (e: WechatMiniprogram.CustomEvent, target: ComponentIns<{}, {}, {}, {}, []>) => any | null
270
270
  setDataHandler: (data: object, target: ComponentIns<{}, {}, {}, {}, []>) => any | null
271
271
  forceFlushSync: boolean,
272
272
  webRouteConfig: object,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/core",
3
- "version": "2.9.73",
3
+ "version": "2.10.1",
4
4
  "description": "mpx runtime core",
5
5
  "keywords": [
6
6
  "miniprogram",
@@ -19,24 +19,25 @@
19
19
  ],
20
20
  "main": "src/index.js",
21
21
  "dependencies": {
22
- "@mpxjs/utils": "^2.9.73",
22
+ "@mpxjs/utils": "^2.10.0",
23
23
  "lodash": "^4.1.1",
24
24
  "miniprogram-api-typings": "^3.10.0"
25
25
  },
26
26
  "peerDependencies": {
27
- "@d11/react-native-fast-image": "^8.6.12",
27
+ "@d11/react-native-fast-image": "*",
28
28
  "@mpxjs/api-proxy": "^2.9.0",
29
29
  "@mpxjs/store": "^2.9.0",
30
- "@react-navigation/native": "^7.0.3",
31
- "@react-navigation/stack": "^7.0.4",
30
+ "@react-navigation/native": "*",
31
+ "@react-navigation/native-stack": "*",
32
32
  "react": "*",
33
33
  "react-native": "*",
34
- "react-native-gesture-handler": "^2.19.0",
35
- "react-native-linear-gradient": "^2.8.3",
36
- "react-native-reanimated": "^3.15.2",
37
- "react-native-safe-area-context": "^4.14.0",
38
- "react-native-screens": "^4.1.0",
39
- "react-native-webview": "^13.10.5",
34
+ "react-native-gesture-handler": "*",
35
+ "react-native-linear-gradient": "*",
36
+ "react-native-reanimated": "*",
37
+ "react-native-safe-area-context": "*",
38
+ "react-native-screens": "*",
39
+ "react-native-video": "*",
40
+ "react-native-webview": "*",
40
41
  "vue": "^2.7.10",
41
42
  "vue-demi": "^0.14.6",
42
43
  "vue-i18n": "^8.27.2",
@@ -67,7 +68,7 @@
67
68
  "@react-navigation/native": {
68
69
  "optional": true
69
70
  },
70
- "@react-navigation/stack": {
71
+ "@react-navigation/native-stack": {
71
72
  "optional": true
72
73
  },
73
74
  "react-native-safe-area-context": {
@@ -87,6 +88,9 @@
87
88
  },
88
89
  "@d11/react-native-fast-image": {
89
90
  "optional": true
91
+ },
92
+ "react-native-video": {
93
+ "optional": true
90
94
  }
91
95
  },
92
96
  "publishConfig": {
@@ -105,5 +109,5 @@
105
109
  "url": "https://github.com/didi/mpx/issues"
106
110
  },
107
111
  "sideEffects": false,
108
- "gitHead": "296482bcb03ab01081a96dcb41ce37df393c3281"
112
+ "gitHead": "7e4f9ab5528f1ab0ae08fdfad1bfbbb445088848"
109
113
  }
@@ -1,4 +1,4 @@
1
- import { warn, isArray, callWithErrorHandling, isDev } from '@mpxjs/utils'
1
+ import { warn, isArray, callWithErrorHandling, isDev, isReact } from '@mpxjs/utils'
2
2
  import Mpx from '../index'
3
3
 
4
4
  let isFlushing = false
@@ -47,6 +47,14 @@ function findInsertionIndex (id) {
47
47
  }
48
48
 
49
49
  export function nextTick (fn) {
50
+ if (isReact) {
51
+ const p = new Promise((resolve) => {
52
+ setTimeout(() => {
53
+ resolve(fn && fn.call(this))
54
+ })
55
+ })
56
+ return p
57
+ }
50
58
  const p = currentFlushPromise || resolvedPromise
51
59
  return fn ? p.then(this ? fn.bind(this) : fn) : p
52
60
  }
@@ -6,7 +6,7 @@ export default function proxyEventMixin () {
6
6
  __invoke (rawEvent, eventConfig = []) {
7
7
  if (typeof Mpx.config.proxyEventHandler === 'function') {
8
8
  try {
9
- Mpx.config.proxyEventHandler(rawEvent)
9
+ Mpx.config.proxyEventHandler(rawEvent, this)
10
10
  } catch (e) {
11
11
  }
12
12
  }
@@ -12,7 +12,7 @@ export default function proxyEventMixin () {
12
12
  __invoke ($event) {
13
13
  if (typeof Mpx.config.proxyEventHandler === 'function') {
14
14
  try {
15
- Mpx.config.proxyEventHandler($event)
15
+ Mpx.config.proxyEventHandler($event, this)
16
16
  } catch (e) {
17
17
  }
18
18
  }
@@ -23,7 +23,7 @@ export default function proxyEventMixin () {
23
23
  __invoke (rawEvent, eventConfig = []) {
24
24
  if (typeof Mpx.config.proxyEventHandler === 'function') {
25
25
  try {
26
- Mpx.config.proxyEventHandler(rawEvent)
26
+ Mpx.config.proxyEventHandler(rawEvent, this)
27
27
  } catch (e) {}
28
28
  }
29
29
  const location = this.__mpxProxy.options.mpxFileResource
@@ -4,6 +4,7 @@ import { createSelectorQuery } from '@mpxjs/api-proxy'
4
4
  export default function getRefsMixin () {
5
5
  return {
6
6
  [BEFORECREATE] () {
7
+ this.__refCache = {}
7
8
  this.__refs = {}
8
9
  this.$refs = {}
9
10
  this.__getRefs()
@@ -26,21 +27,30 @@ export default function getRefsMixin () {
26
27
  })
27
28
  })
28
29
  },
29
- __getRefVal (type, selectorsConf) {
30
- return (instance) => {
31
- if (instance) {
30
+ __getRefVal (type, selectorsConf, refFnId) {
31
+ if (!this.__refCache[refFnId]) {
32
+ this.__refCache[refFnId] = (instance) => {
32
33
  selectorsConf.forEach((item = []) => {
33
34
  const [prefix, selectors = ''] = item
34
35
  if (selectors) {
35
36
  selectors.trim().split(/\s+/).forEach(selector => {
36
37
  const refKey = prefix + selector
38
+ const refVal = { type, instance, refFnId }
37
39
  this.__refs[refKey] = this.__refs[refKey] || []
38
- this.__refs[refKey].push({ type, instance })
40
+ if (instance) { // mount
41
+ this.__refs[refKey].push(refVal)
42
+ } else { // unmount
43
+ const index = this.__refs[refKey].findIndex(item => item.refFnId === refFnId)
44
+ if (index > -1) {
45
+ this.__refs[refKey].splice(index, 1)
46
+ }
47
+ }
39
48
  })
40
49
  }
41
50
  })
42
51
  }
43
52
  }
53
+ return this.__refCache[refFnId]
44
54
  },
45
55
  __selectRef (selector, refType, all = false) {
46
56
  const splitedSelector = selector.match(/(#|\.)?[^.#]+/g) || []
@@ -6,7 +6,6 @@ import { LIFECYCLE } from '../platform/patch/lifecycle/index'
6
6
  import Mpx from '../index'
7
7
  import { createElement, memo, useRef, useEffect } from 'react'
8
8
  import * as ReactNative from 'react-native'
9
- import { Image } from 'react-native'
10
9
  import { initAppProvides } from './export/inject'
11
10
 
12
11
  const appHooksMap = makeMap(mergeLifecycle(LIFECYCLE).app)
@@ -182,19 +181,20 @@ export default function createApp (options) {
182
181
  }, [])
183
182
 
184
183
  const { initialRouteName, initialParams } = initialRouteRef.current
185
- const headerBackImageProps = Mpx.config.rnConfig.headerBackImageProps || null
184
+ const headerBackImageSource = Mpx.config.rnConfig.headerBackImageSource || null
186
185
  const navScreenOpts = {
187
186
  // 7.x替换headerBackTitleVisible
188
187
  // headerBackButtonDisplayMode: 'minimal',
189
188
  headerBackTitleVisible: false,
190
189
  // 安卓上会出现初始化时闪现导航条的问题
191
- headerShown: false
190
+ headerShown: false,
191
+ // 隐藏导航下的那条线
192
+ headerShadowVisible: false
192
193
  }
193
- if (headerBackImageProps) {
194
- navScreenOpts.headerBackImage = () => {
195
- return createElement(Image, headerBackImageProps)
196
- }
194
+ if (headerBackImageSource) {
195
+ navScreenOpts.headerBackImageSource = headerBackImageSource
197
196
  }
197
+
198
198
  return createElement(SafeAreaProvider,
199
199
  null,
200
200
  createElement(NavigationContainer,
@@ -1,4 +1,4 @@
1
- import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, useState, useCallback, createElement, memo, forwardRef, useImperativeHandle, useContext, Fragment, cloneElement, createContext } from 'react'
1
+ import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, useCallback, 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'
@@ -10,6 +10,7 @@ import mergeOptions from '../../core/mergeOptions'
10
10
  import { queueJob, hasPendingJob } from '../../observer/scheduler'
11
11
  import { createSelectorQuery, createIntersectionObserver } from '@mpxjs/api-proxy'
12
12
  import { IntersectionObserverContext, RouteContext, KeyboardAvoidContext } from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/context'
13
+ import KeyboardAvoidingView from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/KeyboardAvoidingView'
13
14
 
14
15
  const ProviderContext = createContext(null)
15
16
 
@@ -44,7 +45,8 @@ function createEffect (proxy, components) {
44
45
  const getComponent = (tagName) => {
45
46
  if (!tagName) return null
46
47
  if (tagName === 'block') return Fragment
47
- return components[tagName] || getByPath(ReactNative, tagName)
48
+ const appComponents = global.__getAppComponents?.() || {}
49
+ return components[tagName] || appComponents[tagName] || getByPath(ReactNative, tagName)
48
50
  }
49
51
  const innerCreateElement = (type, ...rest) => {
50
52
  if (!type) return null
@@ -115,7 +117,6 @@ const instanceProto = {
115
117
  return createIntersectionObserver(this, opt, this.__intersectionCtx)
116
118
  },
117
119
  __resetInstance () {
118
- this.__refs = {}
119
120
  this.__dispatchedSlotSet = new WeakSet()
120
121
  },
121
122
  __iter (val, fn) {
@@ -442,7 +443,7 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
442
443
  const instanceRef = useRef(null)
443
444
  const propsRef = useRef(null)
444
445
  const intersectionCtx = useContext(IntersectionObserverContext)
445
- const pageId = useContext(RouteContext)
446
+ const { pageId } = useContext(RouteContext) || {}
446
447
  const parentProvides = useContext(ProviderContext)
447
448
  let relation = null
448
449
  if (hasDescendantRelation || hasAncestorRelation) {
@@ -566,33 +567,27 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
566
567
  }
567
568
 
568
569
  if (type === 'page') {
569
- const { Provider, useSafeAreaInsets, GestureHandlerRootView } = global.__navigationHelper
570
+ const { PortalHost, useSafeAreaInsets, GestureHandlerRootView, useHeaderHeight } = global.__navigationHelper
570
571
  const pageConfig = Object.assign({}, global.__mpxPageConfig, currentInject.pageConfig)
571
572
  const Page = ({ navigation, route }) => {
572
- const [enabled, setEnabled] = useState(true)
573
573
  const currentPageId = useMemo(() => ++pageId, [])
574
574
  const intersectionObservers = useRef({})
575
575
  usePageStatus(navigation, currentPageId)
576
-
577
576
  useLayoutEffect(() => {
578
577
  const isCustom = pageConfig.navigationStyle === 'custom'
579
- navigation.setOptions({
578
+ navigation.setOptions(Object.assign({
580
579
  headerShown: !isCustom,
581
580
  title: pageConfig.navigationBarTitleText || '',
582
581
  headerStyle: {
583
582
  backgroundColor: pageConfig.navigationBarBackgroundColor || '#000000'
584
583
  },
585
- headerTintColor: pageConfig.navigationBarTextStyle || 'white'
586
- })
587
- if (__mpx_mode__ === 'android') {
588
- ReactNative.StatusBar.setBarStyle(pageConfig.barStyle || 'dark-content')
589
- ReactNative.StatusBar.setTranslucent(isCustom) // 控制statusbar是否占位
590
- const color = isCustom ? 'transparent' : pageConfig.statusBarColor
591
- color && ReactNative.StatusBar.setBackgroundColor(color)
592
- }
584
+ headerTintColor: pageConfig.navigationBarTextStyle || 'white',
585
+ statusBarTranslucent: true
586
+ }, __mpx_mode__ === 'android' ? { statusBarStyle: pageConfig.statusBarStyle || 'light' } : {}))
593
587
  }, [])
594
588
 
595
589
  const rootRef = useRef(null)
590
+ const keyboardAvoidRef = useRef({ cursorSpacing: 0, ref: null })
596
591
  const onLayout = useCallback(() => {
597
592
  rootRef.current?.measureInWindow((x, y, width, height) => {
598
593
  navigation.layout = { x, y, width, height }
@@ -600,34 +595,34 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
600
595
  }, [])
601
596
 
602
597
  const withKeyboardAvoidingView = (element) => {
603
- if (__mpx_mode__ === 'ios') {
604
- return createElement(KeyboardAvoidContext.Provider,
598
+ return createElement(KeyboardAvoidContext.Provider,
599
+ {
600
+ value: keyboardAvoidRef
601
+ },
602
+ createElement(KeyboardAvoidingView,
605
603
  {
606
- value: setEnabled
607
- },
608
- createElement(ReactNative.KeyboardAvoidingView,
609
- {
610
- style: {
611
- flex: 1
612
- },
613
- contentContainerStyle: {
614
- flex: 1
615
- },
616
- behavior: 'position',
617
- enabled
604
+ style: {
605
+ flex: 1
618
606
  },
619
- element
620
- )
607
+ contentContainerStyle: {
608
+ flex: 1
609
+ }
610
+ },
611
+ element
621
612
  )
622
- }
623
- return element
613
+ )
624
614
  }
625
615
 
626
616
  navigation.insets = useSafeAreaInsets()
627
617
 
628
618
  return createElement(GestureHandlerRootView,
629
619
  {
630
- style: {
620
+ // https://github.com/software-mansion/react-native-reanimated/issues/6639 因存在此问题,iOS在页面上进行定宽来暂时规避
621
+ style: __mpx_mode__ === 'ios' && pageConfig.navigationStyle !== 'custom'
622
+ ? {
623
+ height: ReactNative.Dimensions.get('screen').height - useHeaderHeight()
624
+ }
625
+ : {
631
626
  flex: 1
632
627
  }
633
628
  },
@@ -643,13 +638,16 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
643
638
  },
644
639
  createElement(RouteContext.Provider,
645
640
  {
646
- value: currentPageId
641
+ value: {
642
+ pageId: currentPageId,
643
+ navigation
644
+ }
647
645
  },
648
646
  createElement(IntersectionObserverContext.Provider,
649
647
  {
650
648
  value: intersectionObservers.current
651
649
  },
652
- createElement(Provider,
650
+ createElement(PortalHost,
653
651
  null,
654
652
  createElement(defaultOptions,
655
653
  {
@@ -92,8 +92,8 @@ export function getDefaultOptions ({ type, rawOptions = {} }) {
92
92
  this.__mpxProxy.callHook(UNMOUNTED)
93
93
  }
94
94
  },
95
- serverPrefetch () {
96
- if (this.__mpxProxy) return this.__mpxProxy.callHook(SERVERPREFETCH)
95
+ serverPrefetch (...args) {
96
+ if (this.__mpxProxy) return this.__mpxProxy.callHook(SERVERPREFETCH, args)
97
97
  }
98
98
  }]
99
99
  // 为了在builtMixin中可以使用某些rootMixin实现的特性(如数据响应等),此处builtInMixin在rootMixin之后执行,但是当builtInMixin使用存在对应内建生命周期的目标平台声明周期写法时,可能会出现用户生命周期比builtInMixin中的生命周期先执行的情况,为了避免这种情况发生,builtInMixin应该尽可能使用内建生命周期来编写