@mpxjs/core 2.9.67 → 2.9.70-alpha.0

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 (41) hide show
  1. package/@types/global.d.ts +1 -1
  2. package/package.json +18 -9
  3. package/src/convertor/convertor.js +13 -32
  4. package/src/convertor/getConvertMode.js +1 -0
  5. package/src/convertor/wxToAli.js +3 -3
  6. package/src/convertor/wxToReact.js +1 -1
  7. package/src/convertor/wxToSwan.js +3 -3
  8. package/src/convertor/wxToTenon.js +86 -0
  9. package/src/convertor/wxToWeb.js +3 -3
  10. package/src/core/proxy.js +18 -11
  11. package/src/dynamic/dynamicRenderMixin.js +2 -2
  12. package/src/external/vue.tenon.js +13 -0
  13. package/src/index.js +1 -1
  14. package/src/observer/reactive.js +1 -1
  15. package/src/observer/ref.js +3 -2
  16. package/src/observer/scheduler.js +4 -0
  17. package/src/observer/watch.js +5 -4
  18. package/src/platform/builtInMixins/index.js +5 -0
  19. package/src/platform/builtInMixins/pageStatusMixin.tenon.js +40 -0
  20. package/src/platform/builtInMixins/proxyEventMixin.tenon.js +46 -0
  21. package/src/platform/builtInMixins/styleHelperMixin.ios.js +28 -25
  22. package/src/platform/createApp.ios.js +44 -16
  23. package/src/platform/createApp.js +11 -4
  24. package/src/platform/export/apiInject.tenon.js +1 -0
  25. package/src/platform/export/index.tenon.js +78 -0
  26. package/src/platform/patch/builtInKeysMap.js +1 -1
  27. package/src/platform/patch/{ali/getDefaultOptions.js → getDefaultOptions.ali.js} +3 -3
  28. package/src/platform/patch/{react/getDefaultOptions.ios.js → getDefaultOptions.ios.js} +266 -190
  29. package/src/platform/patch/{wx/getDefaultOptions.js → getDefaultOptions.js} +11 -5
  30. package/src/platform/patch/getDefaultOptions.tenon.js +99 -0
  31. package/src/platform/patch/{web/getDefaultOptions.js → getDefaultOptions.web.js} +5 -5
  32. package/src/platform/patch/index.js +4 -21
  33. package/src/platform/patch/{ali/lifecycle.js → lifecycle/index.ali.js} +2 -0
  34. package/src/platform/patch/lifecycle/index.js +1 -0
  35. package/src/platform/patch/{swan/lifecycle.js → lifecycle/index.swan.js} +2 -0
  36. package/src/platform/patch/lifecycle/index.tenon.js +52 -0
  37. package/src/platform/patch/{web/lifecycle.js → lifecycle/index.web.js} +4 -0
  38. package/src/platform/patch/{wx/lifecycle.js → lifecycle/index.wx.js} +2 -0
  39. package/LICENSE +0 -433
  40. package/src/platform/patch/react/getDefaultOptions.js +0 -1
  41. package/src/platform/patch/swan/getDefaultOptions.js +0 -34
@@ -1,15 +1,15 @@
1
- import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, useCallback, createElement, memo, forwardRef, useImperativeHandle, useContext, createContext, Fragment, cloneElement } from 'react'
1
+ import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, useState, useCallback, createElement, memo, forwardRef, useImperativeHandle, useContext, Fragment, cloneElement } from 'react'
2
2
  import * as ReactNative from 'react-native'
3
- import { ReactiveEffect } from '../../../observer/effect'
4
- import { watch } from '../../../observer/watch'
5
- import { reactive, set, del } from '../../../observer/reactive'
6
- import { hasOwn, isFunction, noop, isObject, getByPath, collectDataset, hump2dash, wrapMethodsWithErrorHandling } from '@mpxjs/utils'
7
- import MpxProxy from '../../../core/proxy'
8
- import { BEFOREUPDATE, ONLOAD, UPDATED, ONSHOW, ONHIDE, ONRESIZE, REACTHOOKSEXEC } from '../../../core/innerLifecycle'
9
- import mergeOptions from '../../../core/mergeOptions'
10
- import { queueJob } from '../../../observer/scheduler'
3
+ import { ReactiveEffect } from '../../observer/effect'
4
+ import { watch } from '../../observer/watch'
5
+ import { reactive, set, del } from '../../observer/reactive'
6
+ import { hasOwn, isFunction, noop, isObject, isArray, getByPath, collectDataset, hump2dash, wrapMethodsWithErrorHandling } from '@mpxjs/utils'
7
+ import MpxProxy from '../../core/proxy'
8
+ import { BEFOREUPDATE, ONLOAD, UPDATED, ONSHOW, ONHIDE, ONRESIZE, REACTHOOKSEXEC } from '../../core/innerLifecycle'
9
+ import mergeOptions from '../../core/mergeOptions'
10
+ import { queueJob, hasPendingJob } from '../../observer/scheduler'
11
11
  import { createSelectorQuery, createIntersectionObserver } from '@mpxjs/api-proxy'
12
- import { IntersectionObserverContext } from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/context'
12
+ import { IntersectionObserverContext, RouteContext, KeyboardAvoidContext } from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/context'
13
13
 
14
14
  function getSystemInfo () {
15
15
  const window = ReactNative.Dimensions.get('window')
@@ -27,15 +27,14 @@ function getSystemInfo () {
27
27
 
28
28
  function createEffect (proxy, components) {
29
29
  const update = proxy.update = () => {
30
- // pre render for props update
31
- if (proxy.propsUpdatedFlag) {
32
- proxy.updatePreRender()
33
- }
30
+ // react update props in child render(async), do not need exec pre render
31
+ // if (proxy.propsUpdatedFlag) {
32
+ // proxy.updatePreRender()
33
+ // }
34
34
  if (proxy.isMounted()) {
35
35
  proxy.callHook(BEFOREUPDATE)
36
36
  proxy.pendingUpdatedFlag = true
37
37
  }
38
- // eslint-disable-next-line symbol-description
39
38
  proxy.stateVersion = Symbol()
40
39
  proxy.onStoreChange && proxy.onStoreChange()
41
40
  }
@@ -49,11 +48,14 @@ function createEffect (proxy, components) {
49
48
  if (!type) return null
50
49
  return createElement(type, ...rest)
51
50
  }
51
+
52
52
  proxy.effect = new ReactiveEffect(() => {
53
53
  // reset instance
54
54
  proxy.target.__resetInstance()
55
55
  return proxy.target.__injectedRender(innerCreateElement, getComponent)
56
56
  }, () => queueJob(update), proxy.scope)
57
+ // render effect允许自触发
58
+ proxy.toggleRecurse(true)
57
59
  }
58
60
 
59
61
  function getRootProps (props) {
@@ -69,126 +71,132 @@ function getRootProps (props) {
69
71
  return rootProps
70
72
  }
71
73
 
72
- function createInstance ({ propsRef, type, rawOptions, currentInject, validProps, components, pageId, intersectionCtx }) {
73
- const instance = Object.create({
74
- setData (data, callback) {
75
- return this.__mpxProxy.forceUpdate(data, { sync: true }, callback)
76
- },
77
- getPageId () {
78
- return pageId
79
- },
80
- __getProps () {
81
- const props = propsRef.current
82
- const propsData = {}
83
- Object.keys(validProps).forEach((key) => {
84
- if (hasOwn(props, key)) {
85
- propsData[key] = props[key]
74
+ const instanceProto = {
75
+ setData (data, callback) {
76
+ return this.__mpxProxy.forceUpdate(data, { sync: true }, callback)
77
+ },
78
+ triggerEvent (eventName, eventDetail) {
79
+ const props = this.__props
80
+ const handler = props && (props['bind' + eventName] || props['catch' + eventName] || props['capture-bind' + eventName] || props['capture-catch' + eventName])
81
+ if (handler && typeof handler === 'function') {
82
+ const timeStamp = +new Date()
83
+ const dataset = collectDataset(props)
84
+ const id = props.id || ''
85
+ const eventObj = {
86
+ type: eventName,
87
+ timeStamp,
88
+ target: {
89
+ id,
90
+ dataset,
91
+ targetDataset: dataset
92
+ },
93
+ currentTarget: {
94
+ id,
95
+ dataset
96
+ },
97
+ detail: eventDetail
98
+ }
99
+ handler.call(this, eventObj)
100
+ }
101
+ },
102
+ getPageId () {
103
+ return this.__pageId
104
+ },
105
+ selectComponent (selector) {
106
+ return this.__selectRef(selector, 'component')
107
+ },
108
+ selectAllComponents (selector) {
109
+ return this.__selectRef(selector, 'component', true)
110
+ },
111
+ createSelectorQuery () {
112
+ return createSelectorQuery().in(this)
113
+ },
114
+ createIntersectionObserver (opt) {
115
+ return createIntersectionObserver(this, opt, this.__intersectionCtx)
116
+ },
117
+ __resetInstance () {
118
+ this.__refs = {}
119
+ this.__dispatchedSlotSet = new WeakSet()
120
+ },
121
+ __iter (val, fn) {
122
+ let i, l, keys, key
123
+ const result = []
124
+ if (isArray(val) || typeof val === 'string') {
125
+ for (i = 0, l = val.length; i < l; i++) {
126
+ result.push(fn.call(this, val[i], i))
127
+ }
128
+ } else if (typeof val === 'number') {
129
+ for (i = 0; i < val; i++) {
130
+ result.push(fn.call(this, i + 1, i))
131
+ }
132
+ } else if (isObject(val)) {
133
+ keys = Object.keys(val)
134
+ for (i = 0, l = keys.length; i < l; i++) {
135
+ key = keys[i]
136
+ result.push(fn.call(this, val[key], key, i))
137
+ }
138
+ }
139
+ return result
140
+ },
141
+ __getProps () {
142
+ const props = this.__props
143
+ const validProps = this.__validProps
144
+ const propsData = {}
145
+ Object.keys(validProps).forEach((key) => {
146
+ if (hasOwn(props, key)) {
147
+ propsData[key] = props[key]
148
+ } else {
149
+ const altKey = hump2dash(key)
150
+ if (hasOwn(props, altKey)) {
151
+ propsData[key] = props[altKey]
86
152
  } else {
87
- const altKey = hump2dash(key)
88
- if (hasOwn(props, altKey)) {
89
- propsData[key] = props[altKey]
90
- } else {
91
- let field = validProps[key]
92
- if (isFunction(field) || field === null) {
93
- field = {
94
- type: field
95
- }
153
+ let field = validProps[key]
154
+ if (isFunction(field) || field === null) {
155
+ field = {
156
+ type: field
96
157
  }
97
- // 处理props默认值
98
- propsData[key] = field.value
99
158
  }
159
+ // 处理props默认值
160
+ propsData[key] = field.value
100
161
  }
101
- })
102
- return propsData
103
- },
104
- __resetInstance () {
105
- this.__refs = {}
106
- this.__dispatchedSlotSet = new WeakSet()
107
- },
108
- __getSlot (name) {
109
- const { children } = propsRef.current
110
- if (children) {
111
- const result = []
112
- if (Array.isArray(children)) {
113
- children.forEach(child => {
114
- if (child?.props?.slot === name) {
115
- result.push(child)
116
- }
117
- })
118
- } else {
119
- if (children?.props?.slot === name) {
120
- result.push(children)
162
+ }
163
+ })
164
+ return propsData
165
+ },
166
+ __getSlot (name, slot) {
167
+ const { children } = this.__props
168
+ if (children) {
169
+ let result = []
170
+ if (isArray(children) && !hasOwn(children, '__slot')) {
171
+ children.forEach(child => {
172
+ if (hasOwn(child, '__slot')) {
173
+ if (child.__slot === name) result.push(...child)
174
+ } else if (child?.props?.slot === name) {
175
+ result.push(child)
121
176
  }
122
- }
123
- return result.filter(item => {
124
- if (!isObject(item) || this.__dispatchedSlotSet.has(item)) return false
125
- this.__dispatchedSlotSet.add(item)
126
- return true
127
177
  })
128
- }
129
- return null
130
- },
131
- __injectedRender: currentInject.render || noop,
132
- __getRefsData: currentInject.getRefsData || noop,
133
- // render helper
134
- _i (val, fn) {
135
- let i, l, keys, key
136
- const result = []
137
- if (Array.isArray(val) || typeof val === 'string') {
138
- for (i = 0, l = val.length; i < l; i++) {
139
- result.push(fn.call(this, val[i], i))
140
- }
141
- } else if (typeof val === 'number') {
142
- for (i = 0; i < val; i++) {
143
- result.push(fn.call(this, i + 1, i))
144
- }
145
- } else if (isObject(val)) {
146
- keys = Object.keys(val)
147
- for (i = 0, l = keys.length; i < l; i++) {
148
- key = keys[i]
149
- result.push(fn.call(this, val[key], key, i))
178
+ } else {
179
+ if (hasOwn(children, '__slot')) {
180
+ if (children.__slot === name) result.push(...children)
181
+ } else if (children?.props?.slot === name) {
182
+ result.push(children)
150
183
  }
151
184
  }
185
+ result = result.filter(item => {
186
+ if (!isObject(item) || this.__dispatchedSlotSet.has(item)) return false
187
+ this.__dispatchedSlotSet.add(item)
188
+ return true
189
+ })
190
+ if (!result.length) return null
191
+ result.__slot = slot
152
192
  return result
153
- },
154
- triggerEvent (eventName, eventDetail) {
155
- const props = propsRef.current
156
- const handler = props && (props['bind' + eventName] || props['catch' + eventName] || props['capture-bind' + eventName] || props['capture-catch' + eventName])
157
- if (handler && typeof handler === 'function') {
158
- const timeStamp = +new Date()
159
- const dataset = collectDataset(props)
160
- const id = props.id || ''
161
- const eventObj = {
162
- type: eventName,
163
- timeStamp,
164
- target: {
165
- id,
166
- dataset,
167
- targetDataset: dataset
168
- },
169
- currentTarget: {
170
- id,
171
- dataset
172
- },
173
- detail: eventDetail
174
- }
175
- handler.call(this, eventObj)
176
- }
177
- },
178
- selectComponent (selector) {
179
- return this.__selectRef(selector, 'component')
180
- },
181
- selectAllComponents (selector) {
182
- return this.__selectRef(selector, 'component', true)
183
- },
184
- createSelectorQuery () {
185
- return createSelectorQuery().in(this)
186
- },
187
- createIntersectionObserver (opt) {
188
- return createIntersectionObserver(this, opt, intersectionCtx)
189
- },
190
- ...rawOptions.methods
191
- }, {
193
+ }
194
+ return null
195
+ }
196
+ }
197
+
198
+ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps, components, pageId, intersectionCtx }) {
199
+ const instance = Object.create(instanceProto, {
192
200
  dataset: {
193
201
  get () {
194
202
  const props = propsRef.current
@@ -203,18 +211,55 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
203
211
  },
204
212
  enumerable: true
205
213
  },
206
- props: {
214
+ __props: {
207
215
  get () {
208
216
  return propsRef.current
209
217
  },
210
- enumerable: true
218
+ enumerable: false
219
+ },
220
+ __pageId: {
221
+ get () {
222
+ return pageId
223
+ },
224
+ enumerable: false
225
+ },
226
+ __intersectionCtx: {
227
+ get () {
228
+ return intersectionCtx
229
+ },
230
+ enumerable: false
231
+ },
232
+ __validProps: {
233
+ get () {
234
+ return validProps
235
+ },
236
+ enumerable: false
237
+ },
238
+ __injectedRender: {
239
+ get () {
240
+ return currentInject.render || noop
241
+ },
242
+ enumerable: false
243
+ },
244
+ __getRefsData: {
245
+ get () {
246
+ return currentInject.getRefsData || noop
247
+ },
248
+ enumerable: false
211
249
  }
212
250
  })
213
251
 
214
- const props = propsRef.current
252
+ // bind this & assign methods
253
+ if (rawOptions.methods) {
254
+ Object.entries(rawOptions.methods).forEach(([key, method]) => {
255
+ instance[key] = method.bind(instance)
256
+ })
257
+ }
215
258
 
216
259
  if (type === 'page') {
260
+ const props = propsRef.current
217
261
  instance.route = props.route.name
262
+ global.__mpxPagesMap = global.__mpxPagesMap || {}
218
263
  global.__mpxPagesMap[props.route.key] = [instance, props.navigation]
219
264
  }
220
265
 
@@ -223,12 +268,10 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
223
268
 
224
269
  Object.assign(proxy, {
225
270
  onStoreChange: null,
226
- // eslint-disable-next-line symbol-description
227
271
  stateVersion: Symbol(),
228
272
  subscribe: (onStoreChange) => {
229
273
  if (!proxy.effect) {
230
274
  createEffect(proxy, components)
231
- // eslint-disable-next-line symbol-description
232
275
  proxy.stateVersion = Symbol()
233
276
  }
234
277
  proxy.onStoreChange = onStoreChange
@@ -266,8 +309,6 @@ function hasPageHook (mpxProxy, hookNames) {
266
309
  })
267
310
  }
268
311
 
269
- const RouteContext = createContext(null)
270
-
271
312
  const triggerPageStatusHook = (mpxProxy, event) => {
272
313
  mpxProxy.callHook(event === 'show' ? ONSHOW : ONHIDE)
273
314
  const pageLifetimes = mpxProxy.options.pageLifetimes
@@ -297,8 +338,8 @@ function usePageEffect (mpxProxy, pageId) {
297
338
  const hasHideHook = hasPageHook(mpxProxy, [ONHIDE, 'hide'])
298
339
  const hasResizeHook = hasPageHook(mpxProxy, [ONRESIZE, 'resize'])
299
340
  if (hasShowHook || hasHideHook || hasResizeHook) {
300
- if (hasOwn(pageStatusContext, pageId)) {
301
- unWatch = watch(() => pageStatusContext[pageId], (newVal) => {
341
+ if (hasOwn(pageStatusMap, pageId)) {
342
+ unWatch = watch(() => pageStatusMap[pageId], (newVal) => {
302
343
  if (newVal === 'show' || newVal === 'hide') {
303
344
  triggerPageStatusHook(mpxProxy, newVal)
304
345
  } else if (/^resize/.test(newVal)) {
@@ -313,32 +354,28 @@ function usePageEffect (mpxProxy, pageId) {
313
354
  }, [])
314
355
  }
315
356
 
316
- const pageStatusContext = reactive({})
317
357
  let pageId = 0
358
+ const pageStatusMap = global.__mpxPageStatusMap = reactive({})
318
359
 
319
360
  function usePageStatus (navigation, pageId) {
320
- let isFocused = true
321
- set(pageStatusContext, pageId, '')
361
+ navigation.pageId = pageId
362
+ set(pageStatusMap, pageId, '')
322
363
  useEffect(() => {
323
364
  const focusSubscription = navigation.addListener('focus', () => {
324
- pageStatusContext[pageId] = 'show'
325
- isFocused = true
365
+ pageStatusMap[pageId] = 'show'
326
366
  })
327
367
  const blurSubscription = navigation.addListener('blur', () => {
328
- pageStatusContext[pageId] = 'hide'
329
- isFocused = false
368
+ pageStatusMap[pageId] = 'hide'
330
369
  })
331
370
  const unWatchAppFocusedState = watch(global.__mpxAppFocusedState, (value) => {
332
- if (isFocused) {
333
- pageStatusContext[pageId] = value
334
- }
371
+ pageStatusMap[pageId] = value
335
372
  })
336
373
 
337
374
  return () => {
338
375
  focusSubscription()
339
376
  blurSubscription()
340
377
  unWatchAppFocusedState()
341
- del(pageStatusContext, pageId)
378
+ del(pageStatusMap, pageId)
342
379
  }
343
380
  }, [navigation])
344
381
  }
@@ -382,20 +419,21 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
382
419
  }
383
420
  }
384
421
 
385
- useEffect(() => {
386
- if (!isFirst) {
387
- // 处理props更新
388
- Object.keys(validProps).forEach((key) => {
389
- if (hasOwn(props, key)) {
390
- instance[key] = props[key]
391
- } else {
392
- const altKey = hump2dash(key)
393
- if (hasOwn(props, altKey)) {
394
- instance[key] = props[altKey]
395
- }
422
+ if (!isFirst) {
423
+ // 处理props更新
424
+ Object.keys(validProps).forEach((key) => {
425
+ if (hasOwn(props, key)) {
426
+ instance[key] = props[key]
427
+ } else {
428
+ const altKey = hump2dash(key)
429
+ if (hasOwn(props, altKey)) {
430
+ instance[key] = props[altKey]
396
431
  }
397
- })
398
- }
432
+ }
433
+ })
434
+ }
435
+
436
+ useEffect(() => {
399
437
  if (proxy.pendingUpdatedFlag) {
400
438
  proxy.pendingUpdatedFlag = false
401
439
  proxy.callHook(UPDATED)
@@ -423,10 +461,21 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
423
461
 
424
462
  useSyncExternalStore(proxy.subscribe, proxy.getSnapshot)
425
463
 
426
- const root = rawOptions.options?.disableMemo ? proxy.effect.run() : useMemo(() => proxy.effect.run(), [proxy.stateVersion])
427
- if (root) {
464
+ if ((rawOptions.options?.disableMemo)) {
465
+ proxy.memoVersion = Symbol()
466
+ }
467
+
468
+ const finalMemoVersion = useMemo(() => {
469
+ if (!hasPendingJob(proxy.update)) {
470
+ proxy.finalMemoVersion = Symbol()
471
+ }
472
+ return proxy.finalMemoVersion
473
+ }, [proxy.stateVersion, proxy.memoVersion])
474
+
475
+ const root = useMemo(() => proxy.effect.run(), [finalMemoVersion])
476
+ if (root && root.props.ishost) {
428
477
  const rootProps = getRootProps(props)
429
- rootProps.style = { ...root.props.style, ...rootProps.style }
478
+ rootProps.style = Object.assign({}, root.props.style, rootProps.style)
430
479
  // update root props
431
480
  return cloneElement(root, rootProps)
432
481
  }
@@ -441,30 +490,27 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
441
490
  const { Provider, useSafeAreaInsets, GestureHandlerRootView } = global.__navigationHelper
442
491
  const pageConfig = Object.assign({}, global.__mpxPageConfig, currentInject.pageConfig)
443
492
  const Page = ({ navigation, route }) => {
493
+ const [enabled, setEnabled] = useState(true)
444
494
  const currentPageId = useMemo(() => ++pageId, [])
445
495
  const intersectionObservers = useRef({})
446
496
  usePageStatus(navigation, currentPageId)
447
497
 
448
498
  useLayoutEffect(() => {
449
499
  const isCustom = pageConfig.navigationStyle === 'custom'
450
- const opt = {}
451
- if (__mpx_mode__ === 'android') {
452
- // opt = {
453
- // statusBarTranslucent: isCustom,
454
- // statusBarStyle: pageConfig.statusBarStyle, // 枚举值 'auto' | 'dark' | 'light' 控制statusbar字体颜色
455
- // statusBarColor: isCustom ? 'transparent' : pageConfig.statusBarColor // 控制statusbar背景颜色
456
- // }
457
- }
458
500
  navigation.setOptions({
459
501
  headerShown: !isCustom,
460
502
  title: pageConfig.navigationBarTitleText || '',
461
503
  headerStyle: {
462
504
  backgroundColor: pageConfig.navigationBarBackgroundColor || '#000000'
463
505
  },
464
- // headerTitleAlign: 'center',
465
- headerTintColor: pageConfig.navigationBarTextStyle || 'white',
466
- ...opt
506
+ headerTintColor: pageConfig.navigationBarTextStyle || 'white'
467
507
  })
508
+ if (__mpx_mode__ === 'android') {
509
+ ReactNative.StatusBar.setBarStyle(pageConfig.barStyle || 'dark-content')
510
+ ReactNative.StatusBar.setTranslucent(isCustom) // 控制statusbar是否占位
511
+ const color = isCustom ? 'transparent' : pageConfig.statusBarColor
512
+ color && ReactNative.StatusBar.setBackgroundColor(color)
513
+ }
468
514
  }, [])
469
515
 
470
516
  const rootRef = useRef(null)
@@ -474,6 +520,30 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
474
520
  })
475
521
  }, [])
476
522
 
523
+ const withKeyboardAvoidingView = (element) => {
524
+ if (__mpx_mode__ === 'ios') {
525
+ return createElement(KeyboardAvoidContext.Provider,
526
+ {
527
+ value: setEnabled
528
+ },
529
+ createElement(ReactNative.KeyboardAvoidingView,
530
+ {
531
+ style: {
532
+ flex: 1
533
+ },
534
+ contentContainerStyle: {
535
+ flex: 1
536
+ },
537
+ behavior: 'position',
538
+ enabled
539
+ },
540
+ element
541
+ )
542
+ )
543
+ }
544
+ return element
545
+ }
546
+
477
547
  navigation.insets = useSafeAreaInsets()
478
548
 
479
549
  return createElement(GestureHandlerRootView,
@@ -482,16 +552,19 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
482
552
  flex: 1
483
553
  }
484
554
  },
485
- createElement(ReactNative.View, {
486
- style: {
487
- flex: 1,
488
- backgroundColor: pageConfig.backgroundColor || '#ffffff'
489
- },
490
- ref: rootRef,
491
- onLayout
492
- },
493
- createElement(Provider,
494
- null,
555
+ withKeyboardAvoidingView(
556
+ createElement(ReactNative.View,
557
+ {
558
+ style: {
559
+ flex: 1,
560
+ backgroundColor: pageConfig.backgroundColor || '#ffffff'
561
+ },
562
+ ref: rootRef,
563
+ onLayout,
564
+ onTouchStart: () => {
565
+ ReactNative.Keyboard.isVisible() && ReactNative.Keyboard.dismiss()
566
+ }
567
+ },
495
568
  createElement(RouteContext.Provider,
496
569
  {
497
570
  value: currentPageId
@@ -500,19 +573,22 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
500
573
  {
501
574
  value: intersectionObservers.current
502
575
  },
503
- createElement(defaultOptions,
504
- {
505
- navigation,
506
- route,
507
- id: currentPageId
508
- }
576
+ createElement(Provider,
577
+ null,
578
+ createElement(defaultOptions,
579
+ {
580
+ navigation,
581
+ route,
582
+ id: currentPageId
583
+ }
584
+ )
509
585
  )
510
586
  )
511
587
  )
512
588
  )
513
589
  )
514
- // todo custom portal host for active route
515
590
  )
591
+ // todo custom portal host for active route
516
592
  }
517
593
  return Page
518
594
  }
@@ -1,7 +1,7 @@
1
1
  import { hasOwn, noop, isFunction, wrapMethodsWithErrorHandling } from '@mpxjs/utils'
2
- import MpxProxy from '../../../core/proxy'
3
- import builtInKeysMap from '../builtInKeysMap'
4
- import mergeOptions from '../../../core/mergeOptions'
2
+ import MpxProxy from '../../core/proxy'
3
+ import builtInKeysMap from './builtInKeysMap'
4
+ import mergeOptions from '../../core/mergeOptions'
5
5
 
6
6
  function transformProperties (properties) {
7
7
  if (!properties) {
@@ -126,7 +126,7 @@ function transformApiForProxy (context, currentInject) {
126
126
  }
127
127
  }
128
128
 
129
- export function filterOptions (options) {
129
+ function filterOptions (options) {
130
130
  const newOptions = {}
131
131
  Object.keys(options).forEach(key => {
132
132
  if (builtInKeysMap[key]) {
@@ -155,7 +155,7 @@ export function filterOptions (options) {
155
155
  return newOptions
156
156
  }
157
157
 
158
- export function initProxy (context, rawOptions, currentInject) {
158
+ function initProxy (context, rawOptions, currentInject) {
159
159
  if (!context.__mpxProxy) {
160
160
  // 提供代理对象需要的api
161
161
  transformApiForProxy(context, currentInject)
@@ -185,6 +185,12 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
185
185
  if (this.__mpxProxy) this.__mpxProxy.unmounted()
186
186
  }
187
187
  }]
188
+ // 百度环境如构造页面,优先使用onInit进行初始化
189
+ if (__mpx_mode__ === 'swan' && type === 'page') {
190
+ rootMixins[0].onInit = function (...params) {
191
+ initProxy(this, rawOptions, currentInject, params)
192
+ }
193
+ }
188
194
  rawOptions.mixins = rawOptions.mixins ? rootMixins.concat(rawOptions.mixins) : rootMixins
189
195
  rawOptions = mergeOptions(rawOptions, type, false)
190
196
  return filterOptions(rawOptions)