@mpxjs/core 2.10.17 → 2.10.18
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 +99 -24
- package/src/platform/createApp.ios.js +2 -19
- package/src/platform/env/navigationHelper.ios.js +3 -2
- package/src/platform/patch/getDefaultOptions.ios.js +99 -55
- package/src/platform/patch/react/getDefaultOptions.ios.js +0 -0
package/@types/global.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// declaration for mpx mode
|
|
2
|
-
declare let __mpx_mode__: 'wx' | 'ali' | 'swan' | 'qq' | 'tt' | 'web' | 'dd' | 'qa' | 'jd' | 'android' | 'ios' | 'harmony'
|
|
2
|
+
declare let __mpx_mode__: 'wx' | 'ali' | 'swan' | 'qq' | 'tt' | 'web' | 'dd' | 'qa' | 'jd' | 'android' | 'ios' | 'harmony' | 'ks'
|
|
3
3
|
|
|
4
4
|
// declaration for mpx env
|
|
5
5
|
declare let __mpx_env__: string
|
package/@types/index.d.ts
CHANGED
|
@@ -115,7 +115,7 @@ interface Context {
|
|
|
115
115
|
refs: ObjectOf<WechatMiniprogram.NodesRef & ComponentIns<{}, {}, {}, {}, []>>
|
|
116
116
|
asyncRefs: ObjectOf<Promise<WechatMiniprogram.NodesRef & ComponentIns<{}, {}, {}, {}, []>>>
|
|
117
117
|
|
|
118
|
-
forceUpdate (
|
|
118
|
+
forceUpdate (data?: object): void
|
|
119
119
|
|
|
120
120
|
selectComponent: ReplaceWxComponentIns['selectComponent']
|
|
121
121
|
selectAllComponents: ReplaceWxComponentIns['selectAllComponents']
|
|
@@ -204,7 +204,7 @@ export interface MpxComponentIns {
|
|
|
204
204
|
|
|
205
205
|
$watch (expr: string | (() => any), handler: WatchHandler | WatchOptWithHandler, options?: WatchOpt): () => void
|
|
206
206
|
|
|
207
|
-
$forceUpdate (
|
|
207
|
+
$forceUpdate (data?: object): void
|
|
208
208
|
|
|
209
209
|
$nextTick (fn: () => void): void
|
|
210
210
|
|
|
@@ -412,7 +412,7 @@ interface MpxConfig {
|
|
|
412
412
|
rnConfig: RnConfig,
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
-
type SupportedMode = 'wx' | 'ali' | 'qq' | 'swan' | 'tt' | 'web' | 'qa'
|
|
415
|
+
type SupportedMode = 'wx' | 'ali' | 'qq' | 'swan' | 'tt' | 'web' | 'qa'| 'ks' | 'jd' | 'dd'
|
|
416
416
|
|
|
417
417
|
interface ImplementOptions {
|
|
418
418
|
modes?: Array<SupportedMode>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpxjs/core",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.18",
|
|
4
4
|
"description": "mpx runtime core",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"miniprogram",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"main": "src/index.js",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@mpxjs/utils": "^2.10.
|
|
22
|
+
"@mpxjs/utils": "^2.10.18",
|
|
23
23
|
"lodash": "^4.1.1",
|
|
24
24
|
"miniprogram-api-typings": "^3.10.0"
|
|
25
25
|
},
|
|
@@ -113,5 +113,5 @@
|
|
|
113
113
|
"url": "https://github.com/didi/mpx/issues"
|
|
114
114
|
},
|
|
115
115
|
"sideEffects": false,
|
|
116
|
-
"gitHead": "
|
|
116
|
+
"gitHead": "8ce11a81959cb4b807d683b14c2d0b72c3991da3"
|
|
117
117
|
}
|
|
@@ -9,6 +9,7 @@ import wxToTtRule from './wxToTt'
|
|
|
9
9
|
import wxToDdRule from './wxToDd'
|
|
10
10
|
import wxToJdRule from './wxToJd'
|
|
11
11
|
import wxToReactRule from './wxToReact'
|
|
12
|
+
import wxToKsRule from './wxToKs'
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* 转换规则包含四点
|
|
@@ -38,7 +39,8 @@ const rulesMap = {
|
|
|
38
39
|
wxToJd: extend({}, defaultConvertRule, wxToJdRule),
|
|
39
40
|
wxToIos: extend({}, defaultConvertRule, wxToReactRule),
|
|
40
41
|
wxToAndroid: extend({}, defaultConvertRule, wxToReactRule),
|
|
41
|
-
wxToHarmony: extend({}, defaultConvertRule, wxToReactRule)
|
|
42
|
+
wxToHarmony: extend({}, defaultConvertRule, wxToReactRule),
|
|
43
|
+
wxToKs: extend({}, defaultConvertRule, wxToKsRule)
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
export function getConvertRule (convertMode) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { error } from '@mpxjs/utils'
|
|
2
|
+
|
|
3
|
+
const BEHAVIORS_MAP = [
|
|
4
|
+
'wx://form-field',
|
|
5
|
+
'wx://form-field-group',
|
|
6
|
+
'wx://form-field-button',
|
|
7
|
+
'wx://component-export'
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
convert (options) {
|
|
12
|
+
if (options.behaviors) {
|
|
13
|
+
options.behaviors.forEach((behavior, idx) => {
|
|
14
|
+
if (BEHAVIORS_MAP.includes(behavior)) {
|
|
15
|
+
error(`Built-in behavior "${behavior}" is not supported in ks environment!`, global.currentResource || global.currentModuleId)
|
|
16
|
+
options.behaviors.splice(idx, 1)
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
package/src/convertor/wxToWeb.js
CHANGED
|
@@ -6,7 +6,8 @@ import {
|
|
|
6
6
|
diffAndCloneA,
|
|
7
7
|
error,
|
|
8
8
|
hasOwn,
|
|
9
|
-
isDev
|
|
9
|
+
isDev,
|
|
10
|
+
getDefaultValueByType
|
|
10
11
|
} from '@mpxjs/utils'
|
|
11
12
|
import { implemented } from '../core/implement'
|
|
12
13
|
|
|
@@ -56,6 +57,12 @@ export default {
|
|
|
56
57
|
return diffAndCloneA(prop.value).clone
|
|
57
58
|
}
|
|
58
59
|
: prop.value
|
|
60
|
+
} else {
|
|
61
|
+
// 没有显式设置value时,根据type自动添加默认值,与微信小程序原生行为保持一致
|
|
62
|
+
const defaultValue = getDefaultValueByType(prop.type, 'web')
|
|
63
|
+
if (defaultValue !== undefined) {
|
|
64
|
+
newProp.default = defaultValue
|
|
65
|
+
}
|
|
59
66
|
}
|
|
60
67
|
props[key] = newProp
|
|
61
68
|
} else {
|
package/src/core/proxy.js
CHANGED
|
@@ -31,8 +31,10 @@ import {
|
|
|
31
31
|
wrapMethodsWithErrorHandling,
|
|
32
32
|
warn,
|
|
33
33
|
error,
|
|
34
|
-
getEnvObj
|
|
34
|
+
getEnvObj,
|
|
35
|
+
def
|
|
35
36
|
} from '@mpxjs/utils'
|
|
37
|
+
import { renderHelperDefs } from '../platform/builtInMixins/renderHelperMixin'
|
|
36
38
|
import {
|
|
37
39
|
BEFORECREATE,
|
|
38
40
|
CREATED,
|
|
@@ -190,6 +192,7 @@ export default class MpxProxy {
|
|
|
190
192
|
this.callHook(CREATED)
|
|
191
193
|
|
|
192
194
|
if (!isWeb && !isReact) {
|
|
195
|
+
this.initRenderHelpers()
|
|
193
196
|
this.initRender()
|
|
194
197
|
}
|
|
195
198
|
|
|
@@ -335,7 +338,7 @@ export default class MpxProxy {
|
|
|
335
338
|
createSelectorQuery: this.target.createSelectorQuery ? this.target.createSelectorQuery.bind(this.target) : envObj.createSelectorQuery.bind(envObj),
|
|
336
339
|
createIntersectionObserver: this.target.createIntersectionObserver ? this.target.createIntersectionObserver.bind(this.target) : envObj.createIntersectionObserver.bind(envObj),
|
|
337
340
|
getPageId: this.target.getPageId.bind(this.target),
|
|
338
|
-
getOpenerEventChannel: this.target.getOpenerEventChannel.bind(this.target)
|
|
341
|
+
getOpenerEventChannel: this.target.getOpenerEventChannel ? this.target.getOpenerEventChannel.bind(this.target) : noop
|
|
339
342
|
}
|
|
340
343
|
])
|
|
341
344
|
if (!isObject(setupResult)) {
|
|
@@ -728,6 +731,15 @@ export default class MpxProxy {
|
|
|
728
731
|
this.toggleRecurse(true)
|
|
729
732
|
}
|
|
730
733
|
|
|
734
|
+
initRenderHelpers () {
|
|
735
|
+
if (this.options.__nativeRender__ || __mpx_mode__ !== 'ks') return
|
|
736
|
+
Object.keys(renderHelperDefs).forEach((key) => {
|
|
737
|
+
if (!hasOwn(this.target, key)) {
|
|
738
|
+
def(this.target, key, renderHelperDefs[key])
|
|
739
|
+
}
|
|
740
|
+
})
|
|
741
|
+
}
|
|
742
|
+
|
|
731
743
|
initRender () {
|
|
732
744
|
if (this.options.__nativeRender__) return this.doRender()
|
|
733
745
|
|
|
@@ -57,8 +57,8 @@ export default class MpxScroll {
|
|
|
57
57
|
const isIntersecting = change.isIntersecting
|
|
58
58
|
this.isIntersecting = isIntersecting
|
|
59
59
|
if (!isIntersecting) {
|
|
60
|
-
// 非 inter section 状态下及时清除
|
|
61
|
-
this.el.style.
|
|
60
|
+
// 非 inter section 状态下及时清除 transform,以免影响正常滚动时元素的 fixed 定位
|
|
61
|
+
this.el.style.transform = ''
|
|
62
62
|
this.pullDownEventRegister && this.pullDownEventRegister.destroy()
|
|
63
63
|
} else {
|
|
64
64
|
this.pullDownEventRegister = new EventRegister(this.el, [
|
|
@@ -103,7 +103,12 @@ export default class MpxScroll {
|
|
|
103
103
|
|
|
104
104
|
transformPage (distance) {
|
|
105
105
|
this.translateY = distance
|
|
106
|
-
|
|
106
|
+
if (distance === 0) {
|
|
107
|
+
// 距离为 0 时移除 transform,避免影响页面 fixed 定位
|
|
108
|
+
this.el.style.transform = ''
|
|
109
|
+
} else {
|
|
110
|
+
this.el.style.transform = `translateY(${distance}px)`
|
|
111
|
+
}
|
|
107
112
|
}
|
|
108
113
|
|
|
109
114
|
onTouchEnd (e) {
|
|
@@ -219,8 +224,15 @@ export default class MpxScroll {
|
|
|
219
224
|
}
|
|
220
225
|
|
|
221
226
|
onReachBottom (onReachBottomDistance, callback) {
|
|
222
|
-
const
|
|
223
|
-
const
|
|
227
|
+
const scrollTop = getScrollTop()
|
|
228
|
+
const scrollHeight = document.documentElement.scrollHeight
|
|
229
|
+
const clientHeight = window.innerHeight
|
|
230
|
+
|
|
231
|
+
// 使用 scrollHeight 判断实际内容高度是否超过视口,只有可滚动时才计算触底
|
|
232
|
+
const scrollable = scrollHeight > clientHeight
|
|
233
|
+
// 距离底部的距离 = 内容总高度 - (当前滚动位置 + 视口高度)
|
|
234
|
+
const distanceToBottom = scrollHeight - (scrollTop + clientHeight)
|
|
235
|
+
const mark = scrollable && (distanceToBottom <= onReachBottomDistance)
|
|
224
236
|
|
|
225
237
|
if (!this.bottomReached && mark) {
|
|
226
238
|
this.bottomReached = true
|
|
@@ -57,14 +57,18 @@ export default function getBuiltInMixins ({ type, rawOptions = {} }) {
|
|
|
57
57
|
}
|
|
58
58
|
// 此为纯增强类mixins,原生模式下不需要注入
|
|
59
59
|
if (!rawOptions.__nativeRender__) {
|
|
60
|
-
|
|
61
|
-
renderHelperMixin(),
|
|
60
|
+
const enhancedMixins = [
|
|
62
61
|
showMixin(type),
|
|
63
62
|
i18nMixin(),
|
|
64
63
|
dynamicRenderHelperMixin(),
|
|
65
64
|
dynamicSlotMixin(),
|
|
66
65
|
dynamicRefsMixin()
|
|
67
|
-
]
|
|
66
|
+
]
|
|
67
|
+
if (__mpx_mode__ !== 'ks') {
|
|
68
|
+
// ks methods 不支持 _ 或者 $ 开头的方法名,所以 ks 不走 methods mixin
|
|
69
|
+
enhancedMixins.unshift(renderHelperMixin())
|
|
70
|
+
}
|
|
71
|
+
bulitInMixins = bulitInMixins.concat(enhancedMixins)
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
return bulitInMixins.filter(item => item)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CREATED, ONLOAD, ONSHOW, ONHIDE, ONRESIZE } from '../../core/innerLifecycle'
|
|
2
|
+
import { isObject } from '@mpxjs/utils'
|
|
2
3
|
|
|
3
4
|
export default function pageStatusMixin (mixinType) {
|
|
4
5
|
if (mixinType === 'page') {
|
|
@@ -12,8 +13,19 @@ export default function pageStatusMixin (mixinType) {
|
|
|
12
13
|
onResize (e) {
|
|
13
14
|
this.__mpxProxy.callHook(ONRESIZE, [e])
|
|
14
15
|
},
|
|
15
|
-
onLoad (
|
|
16
|
-
|
|
16
|
+
onLoad (rawQuery) {
|
|
17
|
+
if (__mpx_mode__ === 'wx' || __mpx_mode__ === 'qq' || __mpx_mode__ === 'tt') {
|
|
18
|
+
const decodedQuery = {}
|
|
19
|
+
// 处理以上平台直接透传encode的结果,给到onload第二个参数供开发者使用
|
|
20
|
+
if (isObject(rawQuery)) {
|
|
21
|
+
for (const key in rawQuery) {
|
|
22
|
+
decodedQuery[key] = decodeURIComponent(rawQuery[key])
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
this.__mpxProxy.callHook(ONLOAD, [rawQuery, decodedQuery])
|
|
26
|
+
} else {
|
|
27
|
+
this.__mpxProxy.callHook(ONLOAD, [rawQuery, rawQuery])
|
|
28
|
+
}
|
|
17
29
|
}
|
|
18
30
|
}
|
|
19
31
|
if (__mpx_mode__ === 'ali') {
|
|
@@ -15,6 +15,52 @@ const setRef = function (target, ref, isAsync) {
|
|
|
15
15
|
}
|
|
16
16
|
})
|
|
17
17
|
}
|
|
18
|
+
const proxyMethods = ['boundingClientRect', 'scrollOffset']
|
|
19
|
+
function rewriteAliCreateSelectorQuery (target) {
|
|
20
|
+
const rawCreateSelectorQuery = target.createSelectorQuery
|
|
21
|
+
target.createSelectorQuery = function (...args) {
|
|
22
|
+
let selectorQuery = rawCreateSelectorQuery.apply(target, args)
|
|
23
|
+
const cbs = []
|
|
24
|
+
|
|
25
|
+
if (typeof selectorQuery === 'undefined') {
|
|
26
|
+
// 兜底 selectorQuery 在ali为 undefined 情况
|
|
27
|
+
// 调用 createSelectorQuery时,组件实例已经被销毁,ali this._originCreateSelectorQuery 返回 undefined。导致后续 selectorQuery[name] 报错
|
|
28
|
+
// 方案:对齐微信,微信实例销毁时,其他调用正常,仅 createSelectorQuery.exec 不执行回调
|
|
29
|
+
// 复现:setTimeout 中调用,倒计时未回调时切换页面
|
|
30
|
+
selectorQuery = {}
|
|
31
|
+
// ['boundingClientRect', 'context', 'exec', 'fields', 'in', 'node', 'scrollOffset', 'select', 'selectAll', 'selectViewport', 'toImage']
|
|
32
|
+
const backupMethodKeys = Object.keys(envObj.createSelectorQuery())
|
|
33
|
+
const backupFn = function () {
|
|
34
|
+
return selectorQuery
|
|
35
|
+
}
|
|
36
|
+
backupMethodKeys.forEach(key => {
|
|
37
|
+
selectorQuery[key] = backupFn
|
|
38
|
+
})
|
|
39
|
+
return selectorQuery
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
proxyMethods.forEach((name) => {
|
|
43
|
+
const originalMethod = selectorQuery[name]
|
|
44
|
+
selectorQuery[name] = function (cb = noop) {
|
|
45
|
+
cbs.push(cb)
|
|
46
|
+
return originalMethod.call(this)
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const originalExec = selectorQuery.exec
|
|
51
|
+
selectorQuery.exec = function (originalCb = noop) {
|
|
52
|
+
const cb = function (results) {
|
|
53
|
+
results.forEach((item, index) => {
|
|
54
|
+
cbs[index] && cbs[index](item)
|
|
55
|
+
})
|
|
56
|
+
originalCb(results)
|
|
57
|
+
}
|
|
58
|
+
return originalExec.call(this, cb)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return selectorQuery
|
|
62
|
+
}
|
|
63
|
+
}
|
|
18
64
|
|
|
19
65
|
export default function getRefsMixin () {
|
|
20
66
|
const refsMixin = {
|
|
@@ -24,8 +70,7 @@ export default function getRefsMixin () {
|
|
|
24
70
|
this.__getRefs()
|
|
25
71
|
|
|
26
72
|
if (__mpx_mode__ === 'ali') {
|
|
27
|
-
this
|
|
28
|
-
this.createSelectorQuery = this._createSelectorQuery
|
|
73
|
+
rewriteAliCreateSelectorQuery(this)
|
|
29
74
|
}
|
|
30
75
|
},
|
|
31
76
|
methods: {
|
|
@@ -68,51 +113,7 @@ export default function getRefsMixin () {
|
|
|
68
113
|
}
|
|
69
114
|
})
|
|
70
115
|
|
|
71
|
-
const proxyMethods = ['boundingClientRect', 'scrollOffset']
|
|
72
|
-
|
|
73
116
|
Object.assign(refsMixin.methods, {
|
|
74
|
-
_createSelectorQuery (...args) {
|
|
75
|
-
let selectorQuery = this._originCreateSelectorQuery(...args)
|
|
76
|
-
const cbs = []
|
|
77
|
-
|
|
78
|
-
if (typeof selectorQuery === 'undefined') {
|
|
79
|
-
// 兜底 selectorQuery 在ali为 undefined 情况
|
|
80
|
-
// 调用 createSelectorQuery时,组件实例已经被销毁,ali this._originCreateSelectorQuery 返回 undefined。导致后续 selectorQuery[name] 报错
|
|
81
|
-
// 方案:对齐微信,微信实例销毁时,其他调用正常,仅 createSelectorQuery.exec 不执行回调
|
|
82
|
-
// 复现:setTimeout 中调用,倒计时未回调时切换页面
|
|
83
|
-
selectorQuery = {}
|
|
84
|
-
// ['boundingClientRect', 'context', 'exec', 'fields', 'in', 'node', 'scrollOffset', 'select', 'selectAll', 'selectViewport', 'toImage']
|
|
85
|
-
const backupMethodKeys = Object.keys(envObj.createSelectorQuery())
|
|
86
|
-
const backupFn = function () {
|
|
87
|
-
return selectorQuery
|
|
88
|
-
}
|
|
89
|
-
backupMethodKeys.forEach(key => {
|
|
90
|
-
selectorQuery[key] = backupFn
|
|
91
|
-
})
|
|
92
|
-
return selectorQuery
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
proxyMethods.forEach((name) => {
|
|
96
|
-
const originalMethod = selectorQuery[name]
|
|
97
|
-
selectorQuery[name] = function (cb = noop) {
|
|
98
|
-
cbs.push(cb)
|
|
99
|
-
return originalMethod.call(this)
|
|
100
|
-
}
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
const originalExec = selectorQuery.exec
|
|
104
|
-
selectorQuery.exec = function (originalCb = noop) {
|
|
105
|
-
const cb = function (results) {
|
|
106
|
-
results.forEach((item, index) => {
|
|
107
|
-
cbs[index] && cbs[index](item)
|
|
108
|
-
})
|
|
109
|
-
originalCb(results)
|
|
110
|
-
}
|
|
111
|
-
return originalExec.call(this, cb)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return selectorQuery
|
|
115
|
-
},
|
|
116
117
|
selectComponent (selector) {
|
|
117
118
|
return this.$selectComponent(selector)
|
|
118
119
|
},
|
|
@@ -1,44 +1,46 @@
|
|
|
1
1
|
import { getByPath, hasOwn, isObject } from '@mpxjs/utils'
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
for (i = 0; i < val; i++) {
|
|
14
|
-
handler.call(this, i + 1, i)
|
|
15
|
-
}
|
|
16
|
-
} else if (isObject(val)) {
|
|
17
|
-
keys = Object.keys(val)
|
|
18
|
-
for (i = 0, l = keys.length; i < l; i++) {
|
|
19
|
-
key = keys[i]
|
|
20
|
-
handler.call(this, val[key], key, i)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
// collect
|
|
25
|
-
_c (key, value) {
|
|
26
|
-
if (hasOwn(this.__mpxProxy.renderData, key)) {
|
|
27
|
-
return this.__mpxProxy.renderData[key]
|
|
28
|
-
}
|
|
29
|
-
if (value === undefined) {
|
|
30
|
-
value = getByPath(this, key)
|
|
31
|
-
}
|
|
32
|
-
this.__mpxProxy.renderData[key] = value
|
|
33
|
-
return value
|
|
34
|
-
},
|
|
35
|
-
// simple collect
|
|
36
|
-
_sc (key) {
|
|
37
|
-
return (this.__mpxProxy.renderData[key] = this[key])
|
|
38
|
-
},
|
|
39
|
-
_r (skipPre, vnode) {
|
|
40
|
-
this.__mpxProxy.renderWithData(skipPre, vnode)
|
|
3
|
+
export const renderHelperDefs = {
|
|
4
|
+
_i (val, handler) {
|
|
5
|
+
let i, l, keys, key
|
|
6
|
+
if (Array.isArray(val) || typeof val === 'string') {
|
|
7
|
+
for (i = 0, l = val.length; i < l; i++) {
|
|
8
|
+
handler.call(this, val[i], i)
|
|
9
|
+
}
|
|
10
|
+
} else if (typeof val === 'number') {
|
|
11
|
+
for (i = 0; i < val; i++) {
|
|
12
|
+
handler.call(this, i + 1, i)
|
|
41
13
|
}
|
|
14
|
+
} else if (isObject(val)) {
|
|
15
|
+
keys = Object.keys(val)
|
|
16
|
+
for (i = 0, l = keys.length; i < l; i++) {
|
|
17
|
+
key = keys[i]
|
|
18
|
+
handler.call(this, val[key], key, i)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
// collect
|
|
23
|
+
_c (key, value) {
|
|
24
|
+
if (hasOwn(this.__mpxProxy.renderData, key)) {
|
|
25
|
+
return this.__mpxProxy.renderData[key]
|
|
26
|
+
}
|
|
27
|
+
if (value === undefined) {
|
|
28
|
+
value = getByPath(this, key)
|
|
42
29
|
}
|
|
30
|
+
this.__mpxProxy.renderData[key] = value
|
|
31
|
+
return value
|
|
32
|
+
},
|
|
33
|
+
// simple collect
|
|
34
|
+
_sc (key) {
|
|
35
|
+
return (this.__mpxProxy.renderData[key] = this[key])
|
|
36
|
+
},
|
|
37
|
+
_r (skipPre, vnode) {
|
|
38
|
+
this.__mpxProxy.renderWithData(skipPre, vnode)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export default function renderHelperMixin () {
|
|
43
|
+
return {
|
|
44
|
+
methods: renderHelperDefs
|
|
43
45
|
}
|
|
44
46
|
}
|
|
@@ -1,33 +1,74 @@
|
|
|
1
|
-
import { isObject, isArray, dash2hump, cached, isEmptyObject, hasOwn } from '@mpxjs/utils'
|
|
2
|
-
import {
|
|
1
|
+
import { isObject, isArray, dash2hump, cached, isEmptyObject, hasOwn, getFocusedNavigation } from '@mpxjs/utils'
|
|
2
|
+
import { StyleSheet, Dimensions } from 'react-native'
|
|
3
|
+
import { reactive } from '../../observer/reactive'
|
|
3
4
|
import Mpx from '../../index'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
global.__mpxAppDimensionsInfo = {
|
|
7
|
+
window: Dimensions.get('window'),
|
|
8
|
+
screen: Dimensions.get('screen')
|
|
8
9
|
}
|
|
9
|
-
|
|
10
|
+
global.__mpxSizeCount = 0
|
|
11
|
+
global.__mpxPageSizeCountMap = reactive({})
|
|
10
12
|
|
|
11
|
-
function
|
|
13
|
+
global.__GCC = function (className, classMap, classMapValueCache) {
|
|
14
|
+
if (!classMapValueCache.has(className)) {
|
|
15
|
+
const styleObj = classMap[className]?.(global.__formatValue)
|
|
16
|
+
styleObj && classMapValueCache.set(className, styleObj)
|
|
17
|
+
}
|
|
18
|
+
return classMapValueCache.get(className)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let dimensionsInfoInitialized = false
|
|
22
|
+
function useDimensionsInfo (dimensions) {
|
|
23
|
+
dimensionsInfoInitialized = true
|
|
12
24
|
if (typeof Mpx.config.rnConfig?.customDimensions === 'function') {
|
|
13
25
|
dimensions = Mpx.config.rnConfig.customDimensions(dimensions) || dimensions
|
|
14
26
|
}
|
|
15
|
-
|
|
16
|
-
|
|
27
|
+
global.__mpxAppDimensionsInfo.window = dimensions.window
|
|
28
|
+
global.__mpxAppDimensionsInfo.screen = dimensions.screen
|
|
17
29
|
}
|
|
18
30
|
|
|
19
|
-
|
|
31
|
+
function getPageSize (window = global.__mpxAppDimensionsInfo.screen) {
|
|
32
|
+
return window.width + 'x' + window.height
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
Dimensions.addEventListener('change', ({ window, screen }) => {
|
|
36
|
+
const oldScreen = getPageSize(global.__mpxAppDimensionsInfo.screen)
|
|
37
|
+
useDimensionsInfo({ window, screen })
|
|
38
|
+
|
|
39
|
+
// 对比 screen 高宽是否存在变化
|
|
40
|
+
if (getPageSize(screen) === oldScreen) return
|
|
20
41
|
|
|
42
|
+
global.__classCaches?.forEach(cache => cache?.clear())
|
|
43
|
+
|
|
44
|
+
// 更新全局和栈顶页面的标记,其他后台页面的标记在show之后更新
|
|
45
|
+
global.__mpxSizeCount++
|
|
46
|
+
|
|
47
|
+
const navigation = getFocusedNavigation()
|
|
48
|
+
|
|
49
|
+
if (navigation) {
|
|
50
|
+
global.__mpxPageSizeCountMap[navigation.pageId] = global.__mpxSizeCount
|
|
51
|
+
if (hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
52
|
+
global.__mpxPageStatusMap[navigation.pageId] = `resize${global.__mpxSizeCount}`
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
// TODO: 1 目前测试鸿蒙下折叠屏screen固定为展开状态下屏幕尺寸,仅window会变化,且window包含状态栏高度
|
|
58
|
+
// TODO: 2 存在部分安卓折叠屏机型在折叠/展开切换时,Dimensions监听到的width/height尺寸错误,并触发多次问题
|
|
21
59
|
function rpx (value) {
|
|
60
|
+
const screenInfo = global.__mpxAppDimensionsInfo.screen
|
|
22
61
|
// rn 单位 dp = 1(css)px = 1 物理像素 * pixelRatio(像素比)
|
|
23
62
|
// px = rpx * (750 / 屏幕宽度)
|
|
24
|
-
return value * width / 750
|
|
63
|
+
return value * screenInfo.width / 750
|
|
25
64
|
}
|
|
26
65
|
function vw (value) {
|
|
27
|
-
|
|
66
|
+
const screenInfo = global.__mpxAppDimensionsInfo.screen
|
|
67
|
+
return value * screenInfo.width / 100
|
|
28
68
|
}
|
|
29
69
|
function vh (value) {
|
|
30
|
-
|
|
70
|
+
const screenInfo = global.__mpxAppDimensionsInfo.screen
|
|
71
|
+
return value * screenInfo.height / 100
|
|
31
72
|
}
|
|
32
73
|
|
|
33
74
|
const unit = {
|
|
@@ -38,8 +79,14 @@ const unit = {
|
|
|
38
79
|
|
|
39
80
|
const empty = {}
|
|
40
81
|
|
|
41
|
-
function formatValue (value) {
|
|
42
|
-
if (
|
|
82
|
+
function formatValue (value, unitType) {
|
|
83
|
+
if (!dimensionsInfoInitialized) useDimensionsInfo(global.__mpxAppDimensionsInfo)
|
|
84
|
+
if (unitType === 'hairlineWidth') {
|
|
85
|
+
return StyleSheet.hairlineWidth
|
|
86
|
+
}
|
|
87
|
+
if (unitType && typeof unit[unitType] === 'function') {
|
|
88
|
+
return unit[unitType](+value)
|
|
89
|
+
}
|
|
43
90
|
const matched = unitRegExp.exec(value)
|
|
44
91
|
if (matched) {
|
|
45
92
|
if (!matched[2] || matched[2] === 'px') {
|
|
@@ -180,29 +227,57 @@ function isNativeStyle (style) {
|
|
|
180
227
|
)
|
|
181
228
|
}
|
|
182
229
|
|
|
230
|
+
function getMediaStyle (media) {
|
|
231
|
+
if (!media || !media.length) return {}
|
|
232
|
+
const { width } = global.__mpxAppDimensionsInfo.screen
|
|
233
|
+
return media.reduce((styleObj, item) => {
|
|
234
|
+
const { options = {}, value = {} } = item
|
|
235
|
+
const { minWidth, maxWidth } = options
|
|
236
|
+
if (!isNaN(minWidth) && !isNaN(maxWidth) && width >= minWidth && width <= maxWidth) {
|
|
237
|
+
Object.assign(styleObj, value)
|
|
238
|
+
} else if (!isNaN(minWidth) && width >= minWidth) {
|
|
239
|
+
Object.assign(styleObj, value)
|
|
240
|
+
} else if (!isNaN(maxWidth) && width <= maxWidth) {
|
|
241
|
+
Object.assign(styleObj, value)
|
|
242
|
+
}
|
|
243
|
+
return styleObj
|
|
244
|
+
}, {})
|
|
245
|
+
}
|
|
246
|
+
|
|
183
247
|
export default function styleHelperMixin () {
|
|
184
248
|
return {
|
|
185
249
|
methods: {
|
|
250
|
+
__getSizeCount () {
|
|
251
|
+
return global.__mpxPageSizeCountMap[this.__pageId]
|
|
252
|
+
},
|
|
186
253
|
__getClass (staticClass, dynamicClass) {
|
|
187
254
|
return concat(staticClass, stringifyDynamicClass(dynamicClass))
|
|
188
255
|
},
|
|
189
256
|
__getStyle (staticClass, dynamicClass, staticStyle, dynamicStyle, hide) {
|
|
190
257
|
const isNativeStaticStyle = staticStyle && isNativeStyle(staticStyle)
|
|
191
258
|
let result = isNativeStaticStyle ? [] : {}
|
|
192
|
-
const mergeResult = isNativeStaticStyle ? (
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const appClassMap = global.__getAppClassMap?.() || {}
|
|
259
|
+
const mergeResult = isNativeStaticStyle ? (...args) => result.push(...args) : (...args) => Object.assign(result, ...args)
|
|
260
|
+
// 使用一下 __getSizeCount 触发其 get
|
|
261
|
+
this.__getSizeCount()
|
|
196
262
|
|
|
197
263
|
if (staticClass || dynamicClass) {
|
|
198
264
|
// todo 当前为了复用小程序unocss产物,暂时进行mpEscape,等后续正式支持unocss后可不进行mpEscape
|
|
199
265
|
const classString = mpEscape(concat(staticClass, stringifyDynamicClass(dynamicClass)))
|
|
266
|
+
|
|
200
267
|
classString.split(/\s+/).forEach((className) => {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
268
|
+
let localStyle, appStyle
|
|
269
|
+
if (localStyle = this.__getClassStyle?.(className)) {
|
|
270
|
+
if (localStyle._media?.length) {
|
|
271
|
+
mergeResult(localStyle._default, getMediaStyle(localStyle._media))
|
|
272
|
+
} else {
|
|
273
|
+
mergeResult(localStyle)
|
|
274
|
+
}
|
|
275
|
+
} else if (appStyle = global.__getAppClassStyle?.(className)) {
|
|
276
|
+
if (appStyle._media?.length) {
|
|
277
|
+
mergeResult(appStyle._default, getMediaStyle(appStyle._media))
|
|
278
|
+
} else {
|
|
279
|
+
mergeResult(appStyle)
|
|
280
|
+
}
|
|
206
281
|
} else if (isObject(this.__props[className])) {
|
|
207
282
|
// externalClasses必定以对象形式传递下来
|
|
208
283
|
mergeResult(this.__props[className])
|
|
@@ -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,7 +70,7 @@ 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, {
|
|
@@ -208,22 +204,9 @@ export default function createApp (options) {
|
|
|
208
204
|
if (Mpx.config.rnConfig.disableAppStateListener) return
|
|
209
205
|
onAppStateChange(state)
|
|
210
206
|
})
|
|
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
207
|
return () => {
|
|
224
208
|
appState.state = 'exit'
|
|
225
209
|
changeSubscription && changeSubscription.remove()
|
|
226
|
-
resizeSubScription && resizeSubScription.remove()
|
|
227
210
|
}
|
|
228
211
|
}, [])
|
|
229
212
|
|
|
@@ -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
|
})
|
|
@@ -302,6 +302,7 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
|
|
|
302
302
|
global.__mpxPagesMap = global.__mpxPagesMap || {}
|
|
303
303
|
global.__mpxPagesMap[props.route.key] = [instance, props.navigation]
|
|
304
304
|
setFocusedNavigation(props.navigation)
|
|
305
|
+
set(global.__mpxPageSizeCountMap, pageId, global.__mpxSizeCount)
|
|
305
306
|
// App onLaunch 在 Page created 之前执行
|
|
306
307
|
if (!global.__mpxAppHotLaunched && global.__mpxAppOnLaunch) {
|
|
307
308
|
global.__mpxAppOnLaunch(props.navigation)
|
|
@@ -313,14 +314,14 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
|
|
|
313
314
|
|
|
314
315
|
if (type === 'page') {
|
|
315
316
|
const props = propsRef.current
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
if (isObject(
|
|
319
|
-
for (const key in
|
|
320
|
-
|
|
317
|
+
const decodedQuery = {}
|
|
318
|
+
const rawQuery = props.route.params || {}
|
|
319
|
+
if (isObject(rawQuery)) {
|
|
320
|
+
for (const key in rawQuery) {
|
|
321
|
+
decodedQuery[key] = decodeURIComponent(rawQuery[key])
|
|
321
322
|
}
|
|
322
323
|
}
|
|
323
|
-
proxy.callHook(ONLOAD, [
|
|
324
|
+
proxy.callHook(ONLOAD, [rawQuery, decodedQuery])
|
|
324
325
|
}
|
|
325
326
|
|
|
326
327
|
Object.assign(proxy, {
|
|
@@ -375,9 +376,18 @@ const triggerPageStatusHook = (mpxProxy, event) => {
|
|
|
375
376
|
}
|
|
376
377
|
}
|
|
377
378
|
|
|
378
|
-
const triggerResizeEvent = (mpxProxy) => {
|
|
379
|
-
const
|
|
379
|
+
const triggerResizeEvent = (mpxProxy, sizeRef) => {
|
|
380
|
+
const oldSize = sizeRef.current.size
|
|
380
381
|
const systemInfo = getSystemInfo()
|
|
382
|
+
const newSize = systemInfo.size
|
|
383
|
+
|
|
384
|
+
if (oldSize && oldSize.windowWidth === newSize.windowWidth && oldSize.windowHeight === newSize.windowHeight) {
|
|
385
|
+
return
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
Object.assign(sizeRef.current, systemInfo)
|
|
389
|
+
|
|
390
|
+
const type = mpxProxy.options.__type__
|
|
381
391
|
const target = mpxProxy.target
|
|
382
392
|
mpxProxy.callHook(ONRESIZE, [systemInfo])
|
|
383
393
|
if (type === 'page') {
|
|
@@ -389,6 +399,8 @@ const triggerResizeEvent = (mpxProxy) => {
|
|
|
389
399
|
}
|
|
390
400
|
|
|
391
401
|
function usePageEffect (mpxProxy, pageId) {
|
|
402
|
+
const sizeRef = useRef(getSystemInfo())
|
|
403
|
+
|
|
392
404
|
useEffect(() => {
|
|
393
405
|
let unWatch
|
|
394
406
|
const hasShowHook = hasPageHook(mpxProxy, [ONSHOW, 'show'])
|
|
@@ -399,21 +411,29 @@ function usePageEffect (mpxProxy, pageId) {
|
|
|
399
411
|
unWatch = watch(() => pageStatusMap[pageId], (newVal) => {
|
|
400
412
|
if (newVal === 'show' || newVal === 'hide') {
|
|
401
413
|
triggerPageStatusHook(mpxProxy, newVal)
|
|
414
|
+
// 仅在尺寸确实变化时才触发resize事件
|
|
415
|
+
triggerResizeEvent(mpxProxy, sizeRef)
|
|
416
|
+
|
|
417
|
+
// 如果当前全局size与pagesize不一致,在show之后触发一次resize事件
|
|
418
|
+
if (newVal === 'show' && global.__mpxPageSizeCountMap[pageId] !== global.__mpxSizeCount) {
|
|
419
|
+
// 刷新__mpxPageSizeCountMap, 每个页面仅会执行一次,直接驱动render刷新
|
|
420
|
+
global.__mpxPageSizeCountMap[pageId] = global.__mpxSizeCount
|
|
421
|
+
}
|
|
402
422
|
} else if (/^resize/.test(newVal)) {
|
|
403
|
-
triggerResizeEvent(mpxProxy)
|
|
423
|
+
triggerResizeEvent(mpxProxy, sizeRef)
|
|
404
424
|
}
|
|
405
425
|
}, { sync: true })
|
|
406
426
|
}
|
|
407
427
|
}
|
|
408
428
|
return () => {
|
|
409
429
|
unWatch && unWatch()
|
|
430
|
+
del(global.__mpxPageSizeCountMap, pageId)
|
|
410
431
|
}
|
|
411
432
|
}, [])
|
|
412
433
|
}
|
|
413
434
|
|
|
414
435
|
let pageId = 0
|
|
415
436
|
const pageStatusMap = global.__mpxPageStatusMap = reactive({})
|
|
416
|
-
|
|
417
437
|
function usePageStatus (navigation, pageId) {
|
|
418
438
|
navigation.pageId = pageId
|
|
419
439
|
if (!hasOwn(pageStatusMap, pageId)) {
|
|
@@ -486,7 +506,17 @@ function getLayoutData (headerHeight) {
|
|
|
486
506
|
// 在横屏状态下 screen.height = window.height + bottomVirtualHeight
|
|
487
507
|
// 在正常状态 screen.height = window.height + bottomVirtualHeight + statusBarHeight
|
|
488
508
|
const isLandscape = screenDimensions.height < screenDimensions.width
|
|
489
|
-
|
|
509
|
+
let bottomVirtualHeight = 0
|
|
510
|
+
if (ReactNative.Platform.OS === 'android') {
|
|
511
|
+
if (isLandscape) {
|
|
512
|
+
bottomVirtualHeight = screenDimensions.height - windowDimensions.height
|
|
513
|
+
} else {
|
|
514
|
+
bottomVirtualHeight = initialWindowMetrics?.insets?.bottom || 0
|
|
515
|
+
if (typeof mpxGlobal.__mpx.config?.rnConfig?.getBottomVirtualHeight === 'function') {
|
|
516
|
+
bottomVirtualHeight = mpxGlobal.__mpx.config?.rnConfig?.getBottomVirtualHeight() || 0
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
490
520
|
return {
|
|
491
521
|
left: 0,
|
|
492
522
|
top: headerHeight,
|
|
@@ -519,7 +549,7 @@ export function PageWrapperHOC (WrappedComponent, pageConfig = {}) {
|
|
|
519
549
|
navigation.layout = getLayoutData(headerHeight)
|
|
520
550
|
|
|
521
551
|
useEffect(() => {
|
|
522
|
-
const dimensionListener = ReactNative.Dimensions.addEventListener('change', ({ screen }) => {
|
|
552
|
+
const dimensionListener = ReactNative.Dimensions.addEventListener('change', ({ window, screen }) => {
|
|
523
553
|
navigation.layout = getLayoutData(headerHeight)
|
|
524
554
|
})
|
|
525
555
|
return () => dimensionListener?.remove()
|
|
@@ -529,6 +559,8 @@ export function PageWrapperHOC (WrappedComponent, pageConfig = {}) {
|
|
|
529
559
|
usePageStatus(navigation, currentPageId)
|
|
530
560
|
|
|
531
561
|
const withKeyboardAvoidingView = (element) => {
|
|
562
|
+
if (currentPageConfig.disableKeyboardAvoiding) return element
|
|
563
|
+
const MpxKeyboardAvoidingView = require('@mpxjs/webpack-plugin/lib/runtime/components/react/dist/mpx-keyboard-avoiding-view').default
|
|
532
564
|
return createElement(KeyboardAvoidContext.Provider,
|
|
533
565
|
{
|
|
534
566
|
value: keyboardAvoidRef
|
|
@@ -549,39 +581,53 @@ export function PageWrapperHOC (WrappedComponent, pageConfig = {}) {
|
|
|
549
581
|
// android存在第一次打开insets都返回为0情况,后续会触发第二次渲染后正确
|
|
550
582
|
navigation.insets = useSafeAreaInsets()
|
|
551
583
|
return withKeyboardAvoidingView(
|
|
552
|
-
|
|
584
|
+
createElement(ReactNative.View,
|
|
585
|
+
{
|
|
586
|
+
style: {
|
|
587
|
+
flex: 1,
|
|
588
|
+
// 页面容器背景色
|
|
589
|
+
backgroundColor: currentPageConfig?.backgroundColorContent || '#fff',
|
|
590
|
+
// 解决页面内有元素定位relative left为负值的时候,回退的时候还能看到对应元素问题
|
|
591
|
+
overflow: 'hidden'
|
|
592
|
+
}
|
|
593
|
+
},
|
|
594
|
+
createElement(RouteContext.Provider,
|
|
595
|
+
{
|
|
596
|
+
value: routeContextValRef.current
|
|
597
|
+
},
|
|
598
|
+
createElement(IntersectionObserverContext.Provider,
|
|
553
599
|
{
|
|
554
|
-
|
|
555
|
-
flex: 1,
|
|
556
|
-
// 页面容器背景色
|
|
557
|
-
backgroundColor: currentPageConfig?.backgroundColorContent || '#fff',
|
|
558
|
-
// 解决页面内有元素定位relative left为负值的时候,回退的时候还能看到对应元素问题
|
|
559
|
-
overflow: 'hidden'
|
|
560
|
-
}
|
|
600
|
+
value: intersectionObservers.current
|
|
561
601
|
},
|
|
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
|
-
)
|
|
602
|
+
createElement(PortalHost,
|
|
603
|
+
null,
|
|
604
|
+
createElement(WrappedComponent, {
|
|
605
|
+
...props,
|
|
606
|
+
navigation,
|
|
607
|
+
route,
|
|
608
|
+
id: currentPageId
|
|
609
|
+
})
|
|
580
610
|
)
|
|
611
|
+
)
|
|
581
612
|
)
|
|
613
|
+
)
|
|
582
614
|
)
|
|
583
615
|
}
|
|
584
616
|
}
|
|
617
|
+
|
|
618
|
+
function updateProps (instance, props, validProps) {
|
|
619
|
+
Object.keys(validProps).forEach((key) => {
|
|
620
|
+
if (hasOwn(props, key)) {
|
|
621
|
+
instance[key] = props[key]
|
|
622
|
+
} else {
|
|
623
|
+
const altKey = hump2dash(key)
|
|
624
|
+
if (hasOwn(props, altKey)) {
|
|
625
|
+
instance[key] = props[altKey]
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
})
|
|
629
|
+
}
|
|
630
|
+
|
|
585
631
|
export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
586
632
|
rawOptions = mergeOptions(rawOptions, type, false)
|
|
587
633
|
const componentsMap = currentInject.componentsMap
|
|
@@ -634,16 +680,14 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
634
680
|
|
|
635
681
|
if (!isFirst) {
|
|
636
682
|
// 处理props更新
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
}
|
|
646
|
-
})
|
|
683
|
+
if (Mpx.config.forceFlushSync) {
|
|
684
|
+
// 避免开启forceFlushSync时react报错:Cannot update a component while rendering a different component
|
|
685
|
+
Promise.resolve().then(() => {
|
|
686
|
+
updateProps(instance, props, validProps)
|
|
687
|
+
})
|
|
688
|
+
} else {
|
|
689
|
+
updateProps(instance, props, validProps)
|
|
690
|
+
}
|
|
647
691
|
}
|
|
648
692
|
|
|
649
693
|
useEffect(() => {
|
|
File without changes
|