@mpxjs/core 2.9.70-alpha.1 → 2.9.70-alpha.3
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/package.json +6 -6
- package/src/convertor/wxToReact.js +1 -1
- package/src/core/mergeOptions.js +3 -6
- package/src/core/proxy.js +27 -21
- package/src/index.js +3 -10
- package/src/observer/reactive.js +4 -3
- package/src/platform/builtInMixins/directiveHelperMixin.ios.js +4 -1
- package/src/platform/builtInMixins/index.js +2 -1
- package/src/platform/builtInMixins/proxyEventMixin.web.js +53 -5
- package/src/platform/builtInMixins/relationsMixin.ios.js +67 -0
- package/src/platform/builtInMixins/styleHelperMixin.ios.js +1 -1
- package/src/platform/createApp.ios.js +55 -54
- package/src/platform/createApp.js +25 -29
- package/src/platform/env/event.js +105 -0
- package/src/platform/env/index.ios.js +61 -0
- package/src/platform/env/index.js +8 -0
- package/src/platform/env/index.web.js +48 -0
- package/src/{external → platform/env}/vuePlugin.js +10 -4
- package/src/platform/export/index.js +1 -1
- package/src/platform/export/{apiInject.js → inject.js} +16 -26
- package/src/platform/patch/getDefaultOptions.ios.js +115 -38
- package/src/platform/patch/getDefaultOptions.js +0 -2
- package/src/external/vue.js +0 -1
- package/src/external/vue.web.js +0 -6
- /package/src/{external → platform/env}/vue.tenon.js +0 -0
- /package/src/platform/export/{apiInject.web.js → inject.web.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' | 'dd' | 'qa' | 'jd' | '
|
|
2
|
+
declare let __mpx_mode__: 'wx' | 'ali' | 'swan' | 'qq' | 'tt' | 'web' | 'dd' | 'qa' | 'jd' | 'android' | 'ios' | 'harmony' | 'tenon'
|
|
3
3
|
|
|
4
4
|
// declaration for mpx env
|
|
5
5
|
declare let __mpx_env__: string
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpxjs/core",
|
|
3
|
-
"version": "2.9.70-alpha.
|
|
3
|
+
"version": "2.9.70-alpha.3",
|
|
4
4
|
"description": "mpx runtime core",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"miniprogram",
|
|
@@ -19,12 +19,11 @@
|
|
|
19
19
|
],
|
|
20
20
|
"main": "src/index.js",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@mpxjs/utils": "
|
|
22
|
+
"@mpxjs/utils": "2.9.70-alpha.0",
|
|
23
23
|
"lodash": "^4.1.1",
|
|
24
24
|
"miniprogram-api-typings": "^3.10.0"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"@ant-design/react-native": "^5.1.3",
|
|
28
27
|
"@d11/react-native-fast-image": "^8.6.12",
|
|
29
28
|
"@hummer/tenon-store": "^1.7.0",
|
|
30
29
|
"@hummer/tenon-vue": "^1.5.1",
|
|
@@ -35,6 +34,7 @@
|
|
|
35
34
|
"react-native": "*",
|
|
36
35
|
"react-native-gesture-handler": "^2.19.0",
|
|
37
36
|
"react-native-linear-gradient": "^2.8.3",
|
|
37
|
+
"react-native-reanimated": "^3.15.2",
|
|
38
38
|
"react-native-safe-area-context": "^4.14.0",
|
|
39
39
|
"react-native-screens": "^4.1.0",
|
|
40
40
|
"react-native-webview": "^13.10.5",
|
|
@@ -62,13 +62,13 @@
|
|
|
62
62
|
"react-native": {
|
|
63
63
|
"optional": true
|
|
64
64
|
},
|
|
65
|
-
"
|
|
65
|
+
"react-native-reanimated": {
|
|
66
66
|
"optional": true
|
|
67
67
|
},
|
|
68
|
-
"@react-navigation/
|
|
68
|
+
"@react-navigation/native": {
|
|
69
69
|
"optional": true
|
|
70
70
|
},
|
|
71
|
-
"@
|
|
71
|
+
"@react-navigation/native-stack": {
|
|
72
72
|
"optional": true
|
|
73
73
|
},
|
|
74
74
|
"react-native-safe-area-context": {
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import { implemented } from '../core/implement'
|
|
6
6
|
|
|
7
7
|
// 暂不支持的wx选项,后期需要各种花式支持
|
|
8
|
-
const unsupported = ['
|
|
8
|
+
const unsupported = ['moved', 'definitionFilter']
|
|
9
9
|
|
|
10
10
|
function convertErrorDesc (key) {
|
|
11
11
|
error(`Options.${key} is not supported in runtime conversion from wx to react native.`, global.currentResource)
|
package/src/core/mergeOptions.js
CHANGED
|
@@ -122,9 +122,10 @@ function extractObservers (options) {
|
|
|
122
122
|
Object.keys(props).forEach(key => {
|
|
123
123
|
const prop = props[key]
|
|
124
124
|
if (prop && prop.observer) {
|
|
125
|
+
let callback = prop.observer
|
|
126
|
+
delete prop.observer
|
|
125
127
|
mergeWatch(key, {
|
|
126
128
|
handler (...rest) {
|
|
127
|
-
let callback = prop.observer
|
|
128
129
|
if (typeof callback === 'string') {
|
|
129
130
|
callback = this[callback]
|
|
130
131
|
}
|
|
@@ -168,11 +169,7 @@ function extractObservers (options) {
|
|
|
168
169
|
cb = this[cb]
|
|
169
170
|
}
|
|
170
171
|
if (typeof cb === 'function') {
|
|
171
|
-
|
|
172
|
-
val = [val]
|
|
173
|
-
old = [old]
|
|
174
|
-
}
|
|
175
|
-
cb.call(this, ...val, ...old)
|
|
172
|
+
Array.isArray(val) ? cb.call(this, ...val) : cb.call(this, val)
|
|
176
173
|
}
|
|
177
174
|
},
|
|
178
175
|
deep,
|
package/src/core/proxy.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { reactive,
|
|
1
|
+
import { reactive, defineReactive } from '../observer/reactive'
|
|
2
2
|
import { ReactiveEffect, pauseTracking, resetTracking } from '../observer/effect'
|
|
3
3
|
import { effectScope } from '../platform/export/index'
|
|
4
4
|
import { watch } from '../observer/watch'
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
} from './innerLifecycle'
|
|
53
53
|
import contextMap from '../dynamic/vnode/context'
|
|
54
54
|
import { getAst } from '../dynamic/astCache'
|
|
55
|
-
import { inject, provide } from '../platform/export/
|
|
55
|
+
import { inject, provide } from '../platform/export/inject'
|
|
56
56
|
|
|
57
57
|
let uid = 0
|
|
58
58
|
|
|
@@ -112,7 +112,7 @@ export default class MpxProxy {
|
|
|
112
112
|
this.uid = uid++
|
|
113
113
|
this.name = options.name || ''
|
|
114
114
|
this.options = options
|
|
115
|
-
this.
|
|
115
|
+
this.shallowReactivePattern = this.options.options?.shallowReactivePattern
|
|
116
116
|
// beforeCreate -> created -> mounted -> unmounted
|
|
117
117
|
this.state = BEFORECREATE
|
|
118
118
|
this.ignoreProxyMap = makeMap(Mpx.config.ignoreProxyWhiteList)
|
|
@@ -146,10 +146,12 @@ export default class MpxProxy {
|
|
|
146
146
|
this.initApi()
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
if (this.
|
|
149
|
+
processShallowReactive (obj) {
|
|
150
|
+
if (this.shallowReactivePattern && isObject(obj)) {
|
|
151
151
|
Object.keys(obj).forEach((key) => {
|
|
152
|
-
if (this.
|
|
152
|
+
if (this.shallowReactivePattern.test(key)) {
|
|
153
|
+
// 命中shallowReactivePattern的属性将其设置为 shallowReactive
|
|
154
|
+
defineReactive(obj, key, obj[key], true)
|
|
153
155
|
Object.defineProperty(obj, key, {
|
|
154
156
|
enumerable: true,
|
|
155
157
|
// set configurable to false to skip defineReactive
|
|
@@ -170,6 +172,8 @@ export default class MpxProxy {
|
|
|
170
172
|
// web中BEFORECREATE钩子通过vue的beforeCreate钩子单独驱动
|
|
171
173
|
this.callHook(BEFORECREATE)
|
|
172
174
|
setCurrentInstance(this)
|
|
175
|
+
this.parent = this.resolveParent()
|
|
176
|
+
this.provides = this.parent ? this.parent.provides : Object.create(null)
|
|
173
177
|
// 在 props/data 初始化之前初始化 inject
|
|
174
178
|
this.initInject()
|
|
175
179
|
this.initProps()
|
|
@@ -194,6 +198,18 @@ export default class MpxProxy {
|
|
|
194
198
|
}
|
|
195
199
|
}
|
|
196
200
|
|
|
201
|
+
resolveParent () {
|
|
202
|
+
if (isReact) {
|
|
203
|
+
return {
|
|
204
|
+
provides: this.target.__parentProvides
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (isFunction(this.target.selectOwnerComponent)) {
|
|
208
|
+
const parent = this.target.selectOwnerComponent()
|
|
209
|
+
return parent ? parent.__mpxProxy : null
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
197
213
|
createRenderTask (isEmptyRender) {
|
|
198
214
|
if ((!this.isMounted() && this.currentRenderTask) || (this.isMounted() && isEmptyRender)) {
|
|
199
215
|
return
|
|
@@ -233,16 +249,6 @@ export default class MpxProxy {
|
|
|
233
249
|
// 页面/组件销毁清除上下文的缓存
|
|
234
250
|
contextMap.remove(this.uid)
|
|
235
251
|
}
|
|
236
|
-
if (!isWeb && this.options.__type__ === 'page') {
|
|
237
|
-
// 小程序页面销毁时移除对应的 provide
|
|
238
|
-
if (isFunction(this.target.getPageId)) {
|
|
239
|
-
const pageId = this.target.getPageId()
|
|
240
|
-
const providesMap = global.__mpxProvidesMap
|
|
241
|
-
if (providesMap.__pages[pageId]) {
|
|
242
|
-
delete providesMap.__pages[pageId]
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
252
|
this.callHook(BEFOREUNMOUNT)
|
|
247
253
|
this.scope?.stop()
|
|
248
254
|
if (this.update) this.update.active = false
|
|
@@ -291,10 +297,10 @@ export default class MpxProxy {
|
|
|
291
297
|
if (isReact) {
|
|
292
298
|
// react模式下props内部对象透传无需深clone,依赖对象深层的数据响应触发子组件更新
|
|
293
299
|
this.props = this.target.__getProps()
|
|
294
|
-
|
|
300
|
+
reactive(this.processShallowReactive(this.props))
|
|
295
301
|
} else {
|
|
296
302
|
this.props = diffAndCloneA(this.target.__getProps(this.options)).clone
|
|
297
|
-
reactive(this.
|
|
303
|
+
reactive(this.processShallowReactive(this.props))
|
|
298
304
|
}
|
|
299
305
|
proxy(this.target, this.props, undefined, false, this.createProxyConflictHandler('props'))
|
|
300
306
|
}
|
|
@@ -334,7 +340,7 @@ export default class MpxProxy {
|
|
|
334
340
|
if (isFunction(dataFn)) {
|
|
335
341
|
Object.assign(this.data, callWithErrorHandling(dataFn.bind(this.target), this, 'data function'))
|
|
336
342
|
}
|
|
337
|
-
reactive(this.
|
|
343
|
+
reactive(this.processShallowReactive(this.data))
|
|
338
344
|
proxy(this.target, this.data, undefined, false, this.createProxyConflictHandler('data'))
|
|
339
345
|
this.collectLocalKeys(this.data)
|
|
340
346
|
}
|
|
@@ -515,7 +521,7 @@ export default class MpxProxy {
|
|
|
515
521
|
if (hasOwn(renderData, key)) {
|
|
516
522
|
const data = renderData[key]
|
|
517
523
|
const firstKey = getFirstKey(key)
|
|
518
|
-
if (!this.localKeysMap[firstKey]
|
|
524
|
+
if (!this.localKeysMap[firstKey]) {
|
|
519
525
|
continue
|
|
520
526
|
}
|
|
521
527
|
// 外部clone,用于只需要clone的场景
|
|
@@ -762,7 +768,7 @@ export default class MpxProxy {
|
|
|
762
768
|
}
|
|
763
769
|
setByPath(this.target, key, data[key])
|
|
764
770
|
})
|
|
765
|
-
this.forceUpdateData
|
|
771
|
+
Object.assign(this.forceUpdateData, data)
|
|
766
772
|
} else {
|
|
767
773
|
this.forceUpdateAll = true
|
|
768
774
|
}
|
package/src/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
import { error, diffAndCloneA, hasOwn, makeMap } from '@mpxjs/utils'
|
|
3
3
|
import { APIs, InstanceAPIs } from './platform/export/api'
|
|
4
|
-
|
|
5
|
-
import { createI18n } from './platform/builtInMixins/i18nMixin'
|
|
4
|
+
import { init } from './platform/env/index'
|
|
6
5
|
|
|
7
6
|
export * from './platform/export/index'
|
|
8
7
|
|
|
@@ -156,12 +155,6 @@ Mpx.config = {
|
|
|
156
155
|
rnConfig: {}
|
|
157
156
|
}
|
|
158
157
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (__mpx_mode__ !== 'web') {
|
|
162
|
-
if (global.i18n) {
|
|
163
|
-
Mpx.i18n = createI18n(global.i18n)
|
|
164
|
-
}
|
|
165
|
-
}
|
|
158
|
+
init(Mpx)
|
|
166
159
|
|
|
167
160
|
export default Mpx
|
package/src/observer/reactive.js
CHANGED
|
@@ -34,6 +34,7 @@ export class Observer {
|
|
|
34
34
|
|
|
35
35
|
constructor (value, shallow) {
|
|
36
36
|
this.value = value
|
|
37
|
+
this.shallow = shallow
|
|
37
38
|
def(value, ObKey, this)
|
|
38
39
|
if (Array.isArray(value)) {
|
|
39
40
|
const augment = hasProto && arrayProtoAugment
|
|
@@ -120,7 +121,7 @@ export function defineReactive (obj, key, val, shallow) {
|
|
|
120
121
|
const getter = property && property.get
|
|
121
122
|
const setter = property && property.set
|
|
122
123
|
|
|
123
|
-
let childOb =
|
|
124
|
+
let childOb = shallow ? getObserver(val) : observe(val)
|
|
124
125
|
Object.defineProperty(obj, key, {
|
|
125
126
|
enumerable: true,
|
|
126
127
|
configurable: true,
|
|
@@ -149,7 +150,7 @@ export function defineReactive (obj, key, val, shallow) {
|
|
|
149
150
|
} else {
|
|
150
151
|
val = newVal
|
|
151
152
|
}
|
|
152
|
-
childOb =
|
|
153
|
+
childOb = shallow ? getObserver(newVal) : observe(newVal)
|
|
153
154
|
dep.notify()
|
|
154
155
|
}
|
|
155
156
|
})
|
|
@@ -175,7 +176,7 @@ export function set (target, key, val) {
|
|
|
175
176
|
target[key] = val
|
|
176
177
|
return val
|
|
177
178
|
}
|
|
178
|
-
defineReactive(ob.value, key, val)
|
|
179
|
+
defineReactive(ob.value, key, val, ob.shallow)
|
|
179
180
|
ob.dep.notify()
|
|
180
181
|
return val
|
|
181
182
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { setByPath } from '@mpxjs/utils'
|
|
1
|
+
import { setByPath, error, parseDataset } from '@mpxjs/utils'
|
|
2
|
+
import Mpx from '../../index'
|
|
2
3
|
|
|
3
4
|
export default function proxyEventMixin () {
|
|
4
5
|
return {
|
|
@@ -19,11 +20,58 @@ export default function proxyEventMixin () {
|
|
|
19
20
|
const value = filterMethod ? (innerFilter[filterMethod] ? innerFilter[filterMethod](originValue) : typeof this[filterMethod] === 'function' && this[filterMethod]) : originValue
|
|
20
21
|
setByPath(this, expr, value)
|
|
21
22
|
},
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
__invoke (rawEvent, eventConfig = []) {
|
|
24
|
+
if (typeof Mpx.config.proxyEventHandler === 'function') {
|
|
25
|
+
try {
|
|
26
|
+
Mpx.config.proxyEventHandler(rawEvent)
|
|
27
|
+
} catch (e) {}
|
|
26
28
|
}
|
|
29
|
+
const location = this.__mpxProxy.options.mpxFileResource
|
|
30
|
+
|
|
31
|
+
if (rawEvent.target && !rawEvent.target._datasetProcessed) {
|
|
32
|
+
const originalDataset = rawEvent.target.dataset
|
|
33
|
+
Object.defineProperty(rawEvent.target, 'dataset', {
|
|
34
|
+
get: () => parseDataset(originalDataset),
|
|
35
|
+
configurable: true,
|
|
36
|
+
enumerable: true
|
|
37
|
+
})
|
|
38
|
+
rawEvent.target._datasetProcessed = true
|
|
39
|
+
}
|
|
40
|
+
if (rawEvent.currentTarget && !rawEvent.currentTarget._datasetProcessed) {
|
|
41
|
+
const originalDataset = rawEvent.currentTarget.dataset
|
|
42
|
+
Object.defineProperty(rawEvent.currentTarget, 'dataset', {
|
|
43
|
+
get: () => parseDataset(originalDataset),
|
|
44
|
+
configurable: true,
|
|
45
|
+
enumerable: true
|
|
46
|
+
})
|
|
47
|
+
rawEvent.currentTarget._datasetProcessed = true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let returnedValue
|
|
51
|
+
eventConfig.forEach((item) => {
|
|
52
|
+
const callbackName = item[0]
|
|
53
|
+
if (callbackName) {
|
|
54
|
+
const params =
|
|
55
|
+
item.length > 1
|
|
56
|
+
? item.slice(1).map((item) => {
|
|
57
|
+
if (item === '__mpx_event__') {
|
|
58
|
+
return rawEvent
|
|
59
|
+
} else {
|
|
60
|
+
return item
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
: [rawEvent]
|
|
64
|
+
if (typeof this[callbackName] === 'function') {
|
|
65
|
+
returnedValue = this[callbackName].apply(this, params)
|
|
66
|
+
} else {
|
|
67
|
+
error(
|
|
68
|
+
`Instance property [${callbackName}] is not function, please check.`,
|
|
69
|
+
location
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
return returnedValue
|
|
27
75
|
}
|
|
28
76
|
}
|
|
29
77
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { BEFORECREATE, MOUNTED, BEFOREUNMOUNT } from '../../core/innerLifecycle'
|
|
2
|
+
|
|
3
|
+
const relationTypeMap = {
|
|
4
|
+
parent: 'child',
|
|
5
|
+
ancestor: 'descendant'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function relationsMixin (mixinType) {
|
|
9
|
+
if (mixinType === 'component') {
|
|
10
|
+
return {
|
|
11
|
+
[BEFORECREATE] () {
|
|
12
|
+
this.__relationNodesMap = {}
|
|
13
|
+
},
|
|
14
|
+
[MOUNTED] () {
|
|
15
|
+
this.__mpxExecRelations('linked')
|
|
16
|
+
},
|
|
17
|
+
[BEFOREUNMOUNT] () {
|
|
18
|
+
this.__mpxExecRelations('unlinked')
|
|
19
|
+
this.__relationNodesMap = {}
|
|
20
|
+
},
|
|
21
|
+
methods: {
|
|
22
|
+
getRelationNodes (path) {
|
|
23
|
+
return this.__relationNodesMap[path] || null
|
|
24
|
+
},
|
|
25
|
+
__mpxExecRelations (type) {
|
|
26
|
+
const relations = this.__mpxProxy.options.relations
|
|
27
|
+
const relationContext = this.__relation
|
|
28
|
+
const currentPath = this.__componentPath
|
|
29
|
+
if (relations && relationContext) {
|
|
30
|
+
Object.keys(relations).forEach((path) => {
|
|
31
|
+
const relation = relations[path]
|
|
32
|
+
const relationType = relation.type
|
|
33
|
+
if ((relationType === 'parent' || relationType === 'ancestor') && relationContext[path]) {
|
|
34
|
+
const target = relationContext[path]
|
|
35
|
+
const targetRelation = target.__mpxProxy.options.relations?.[currentPath]
|
|
36
|
+
if (targetRelation && targetRelation.type === relationTypeMap[relationType] && target.__componentPath === path) {
|
|
37
|
+
if (type === 'linked') {
|
|
38
|
+
this.__mpxLinkRelationNodes(target, currentPath)
|
|
39
|
+
} else if (type === 'unlinked') {
|
|
40
|
+
this.__mpxRemoveRelationNodes(target, currentPath)
|
|
41
|
+
}
|
|
42
|
+
if (typeof targetRelation[type] === 'function') {
|
|
43
|
+
targetRelation[type].call(target, this)
|
|
44
|
+
}
|
|
45
|
+
if (typeof relation[type] === 'function') {
|
|
46
|
+
relation[type].call(this, target)
|
|
47
|
+
}
|
|
48
|
+
this.__relationNodesMap[path] = [target]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
__mpxLinkRelationNodes (target, path) {
|
|
55
|
+
target.__relationNodesMap[path] = target.__relationNodesMap[path] || [] // 父级绑定子级
|
|
56
|
+
target.__relationNodesMap[path].push(this)
|
|
57
|
+
},
|
|
58
|
+
__mpxRemoveRelationNodes (target, path) {
|
|
59
|
+
const relationNodesMap = target.__relationNodesMap
|
|
60
|
+
const arr = relationNodesMap[path] || []
|
|
61
|
+
const index = arr.indexOf(this)
|
|
62
|
+
if (index !== -1) arr.splice(index, 1)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -181,7 +181,7 @@ export default function styleHelperMixin () {
|
|
|
181
181
|
} else if (appClassMap[className]) {
|
|
182
182
|
// todo 全局样式在每个页面和组件中生效,以支持全局原子类,后续支持样式模块复用后可考虑移除
|
|
183
183
|
Object.assign(result, appClassMap[className])
|
|
184
|
-
} else if (
|
|
184
|
+
} else if (isObject(this.__props[className])) {
|
|
185
185
|
// externalClasses必定以对象形式传递下来
|
|
186
186
|
Object.assign(result, this.__props[className])
|
|
187
187
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import transferOptions from '../core/transferOptions'
|
|
2
2
|
import builtInKeysMap from './patch/builtInKeysMap'
|
|
3
|
-
import { makeMap, spreadProp,
|
|
3
|
+
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
7
|
import { createElement, memo, useRef, useEffect } from 'react'
|
|
8
8
|
import * as ReactNative from 'react-native'
|
|
9
|
-
import {
|
|
9
|
+
import { initAppProvides } from './export/inject'
|
|
10
10
|
|
|
11
11
|
const appHooksMap = makeMap(mergeLifecycle(LIFECYCLE).app)
|
|
12
12
|
|
|
@@ -29,22 +29,28 @@ function filterOptions (options, appData) {
|
|
|
29
29
|
return newOptions
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function
|
|
33
|
-
return extend({}, Mpx.prototype, appData)
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default function createApp (option, config = {}) {
|
|
32
|
+
export default function createApp (options) {
|
|
37
33
|
const appData = {}
|
|
38
34
|
|
|
39
35
|
const { NavigationContainer, createStackNavigator, SafeAreaProvider } = global.__navigationHelper
|
|
40
36
|
// app选项目前不需要进行转换
|
|
41
|
-
const { rawOptions, currentInject } = transferOptions(
|
|
37
|
+
const { rawOptions, currentInject } = transferOptions(options, 'app', false)
|
|
38
|
+
initAppProvides(rawOptions.provide, rawOptions)
|
|
42
39
|
const defaultOptions = filterOptions(spreadProp(rawOptions, 'methods'), appData)
|
|
43
|
-
defaultOptions.onAppInit && defaultOptions.onAppInit()
|
|
44
40
|
// 在页面script执行前填充getApp()
|
|
45
41
|
global.getApp = function () {
|
|
46
42
|
return appData
|
|
47
43
|
}
|
|
44
|
+
|
|
45
|
+
// 模拟小程序appInstance在热启动时不会重新创建的行为,在外部创建跟随js context的appInstance
|
|
46
|
+
const appInstance = Object.assign({}, appData, Mpx.prototype)
|
|
47
|
+
|
|
48
|
+
defaultOptions.onShow && global.__mpxAppCbs.show.push(defaultOptions.onShow.bind(appInstance))
|
|
49
|
+
defaultOptions.onHide && global.__mpxAppCbs.hide.push(defaultOptions.onHide.bind(appInstance))
|
|
50
|
+
defaultOptions.onError && global.__mpxAppCbs.error.push(defaultOptions.onError.bind(appInstance))
|
|
51
|
+
defaultOptions.onUnhandledRejection && global.__mpxAppCbs.rejection.push(defaultOptions.onUnhandledRejection.bind(appInstance))
|
|
52
|
+
defaultOptions.onAppInit && defaultOptions.onAppInit()
|
|
53
|
+
|
|
48
54
|
const pages = currentInject.getPages() || {}
|
|
49
55
|
const firstPage = currentInject.firstPage
|
|
50
56
|
const Stack = createStackNavigator()
|
|
@@ -80,63 +86,51 @@ export default function createApp (option, config = {}) {
|
|
|
80
86
|
}
|
|
81
87
|
}
|
|
82
88
|
|
|
83
|
-
global.__mpxAppCbs = global.__mpxAppCbs || {
|
|
84
|
-
show: [],
|
|
85
|
-
hide: [],
|
|
86
|
-
error: []
|
|
87
|
-
}
|
|
88
|
-
|
|
89
89
|
global.__mpxAppLaunched = false
|
|
90
|
-
|
|
91
|
-
global.__mpxAppFocusedState = ref('show')
|
|
92
90
|
global.__mpxOptionsMap[currentInject.moduleId] = memo((props) => {
|
|
93
|
-
const
|
|
94
|
-
if (!instanceRef.current) {
|
|
95
|
-
instanceRef.current = createAppInstance(appData)
|
|
96
|
-
}
|
|
97
|
-
const instance = instanceRef.current
|
|
91
|
+
const firstRef = useRef(true)
|
|
98
92
|
const initialRouteRef = useRef({
|
|
99
93
|
initialRouteName: firstPage,
|
|
100
94
|
initialParams: {}
|
|
101
95
|
})
|
|
96
|
+
if (firstRef.current) {
|
|
97
|
+
// 热启动情况下,app会被销毁重建,将__mpxAppHotLaunched重置保障路由等初始化逻辑正确执行
|
|
98
|
+
global.__mpxAppHotLaunched = false
|
|
99
|
+
// 热启动情况下重置__mpxPagesMap避免页面销毁函数未及时执行时错误地引用到之前的navigation
|
|
100
|
+
global.__mpxPagesMap = {}
|
|
101
|
+
firstRef.current = false
|
|
102
|
+
}
|
|
103
|
+
if (!global.__mpxAppHotLaunched) {
|
|
104
|
+
const { initialRouteName, initialParams } = Mpx.config.rnConfig.parseAppProps?.(props) || {}
|
|
105
|
+
initialRouteRef.current.initialRouteName = initialRouteName || initialRouteRef.current.initialRouteName
|
|
106
|
+
initialRouteRef.current.initialParams = initialParams || initialRouteRef.current.initialParams
|
|
102
107
|
|
|
103
|
-
if (!global.__mpxAppLaunched) {
|
|
104
|
-
const parsed = Mpx.config.rnConfig.parseAppProps?.(props) || {}
|
|
105
|
-
if (parsed.url) {
|
|
106
|
-
const { path, queryObj } = parseUrlQuery(parsed.url)
|
|
107
|
-
Object.assign(initialRouteRef.current, {
|
|
108
|
-
initialRouteName: path.startsWith('/') ? path.slice(1) : path,
|
|
109
|
-
initialParams: queryObj
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
108
|
global.__mpxAppOnLaunch = (navigation) => {
|
|
113
|
-
global.__mpxAppLaunched = true
|
|
114
109
|
const state = navigation.getState()
|
|
115
110
|
Mpx.config.rnConfig.onStateChange?.(state)
|
|
116
111
|
const current = state.routes[state.index]
|
|
117
|
-
|
|
112
|
+
const options = {
|
|
118
113
|
path: current.name,
|
|
119
114
|
query: current.params,
|
|
120
115
|
scene: 0,
|
|
121
116
|
shareTicket: '',
|
|
122
|
-
referrerInfo: {}
|
|
117
|
+
referrerInfo: {},
|
|
118
|
+
isLaunch: true
|
|
119
|
+
}
|
|
120
|
+
global.__mpxEnterOptions = options
|
|
121
|
+
if (!global.__mpxAppLaunched) {
|
|
122
|
+
global.__mpxLaunchOptions = options
|
|
123
|
+
defaultOptions.onLaunch && defaultOptions.onLaunch.call(appInstance, options)
|
|
123
124
|
}
|
|
124
|
-
|
|
125
|
-
|
|
125
|
+
global.__mpxAppCbs.show.forEach((cb) => {
|
|
126
|
+
cb(options)
|
|
127
|
+
})
|
|
128
|
+
global.__mpxAppLaunched = true
|
|
129
|
+
global.__mpxAppHotLaunched = true
|
|
126
130
|
}
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
useEffect(() => {
|
|
130
|
-
if (defaultOptions.onShow) {
|
|
131
|
-
global.__mpxAppCbs.show.push(defaultOptions.onShow.bind(instance))
|
|
132
|
-
}
|
|
133
|
-
if (defaultOptions.onHide) {
|
|
134
|
-
global.__mpxAppCbs.hide.push(defaultOptions.onHide.bind(instance))
|
|
135
|
-
}
|
|
136
|
-
if (defaultOptions.onError) {
|
|
137
|
-
global.__mpxAppCbs.error.push(defaultOptions.onError.bind(instance))
|
|
138
|
-
}
|
|
139
|
-
|
|
140
134
|
const changeSubscription = ReactNative.AppState.addEventListener('change', (currentState) => {
|
|
141
135
|
if (currentState === 'active') {
|
|
142
136
|
let options = global.__mpxEnterOptions
|
|
@@ -158,7 +152,7 @@ export default function createApp (option, config = {}) {
|
|
|
158
152
|
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
159
153
|
global.__mpxPageStatusMap[navigation.pageId] = 'show'
|
|
160
154
|
}
|
|
161
|
-
} else if (currentState === 'inactive') {
|
|
155
|
+
} else if (currentState === 'inactive' || currentState === 'background') {
|
|
162
156
|
global.__mpxAppCbs.hide.forEach((cb) => {
|
|
163
157
|
cb()
|
|
164
158
|
})
|
|
@@ -187,6 +181,19 @@ export default function createApp (option, config = {}) {
|
|
|
187
181
|
}, [])
|
|
188
182
|
|
|
189
183
|
const { initialRouteName, initialParams } = initialRouteRef.current
|
|
184
|
+
const headerBackImageSource = Mpx.config.rnConfig.headerBackImageSource || null
|
|
185
|
+
const navScreenOpts = {
|
|
186
|
+
// 7.x替换headerBackTitleVisible
|
|
187
|
+
// headerBackButtonDisplayMode: 'minimal',
|
|
188
|
+
headerBackTitleVisible: false,
|
|
189
|
+
// 安卓上会出现初始化时闪现导航条的问题
|
|
190
|
+
headerShown: false,
|
|
191
|
+
// 隐藏导航下的那条线
|
|
192
|
+
headerShadowVisible: false
|
|
193
|
+
}
|
|
194
|
+
if (headerBackImageSource) {
|
|
195
|
+
navScreenOpts.headerBackImageSource = headerBackImageSource
|
|
196
|
+
}
|
|
190
197
|
return createElement(SafeAreaProvider,
|
|
191
198
|
null,
|
|
192
199
|
createElement(NavigationContainer,
|
|
@@ -197,13 +204,7 @@ export default function createApp (option, config = {}) {
|
|
|
197
204
|
createElement(Stack.Navigator,
|
|
198
205
|
{
|
|
199
206
|
initialRouteName,
|
|
200
|
-
screenOptions:
|
|
201
|
-
gestureEnabled: true,
|
|
202
|
-
// 7.x替换headerBackTitleVisible
|
|
203
|
-
// headerBackButtonDisplayMode: 'minimal',
|
|
204
|
-
headerBackTitleVisible: false,
|
|
205
|
-
headerMode: 'float'
|
|
206
|
-
}
|
|
207
|
+
screenOptions: navScreenOpts
|
|
207
208
|
},
|
|
208
209
|
...getPageScreens(initialRouteName, initialParams)
|
|
209
210
|
)
|