@mpxjs/core 2.9.66 → 2.9.67
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 +2 -0
- package/@types/index.d.ts +18 -2
- package/package.json +3 -3
- package/src/core/mergeOptions.js +1 -1
- package/src/core/proxy.js +69 -1
- package/src/platform/createApp.ios.js +60 -26
- package/src/platform/createApp.js +3 -1
- package/src/platform/export/apiInject.js +68 -0
- package/src/platform/export/apiInject.web.js +1 -0
- package/src/platform/export/index.js +5 -0
- package/src/platform/export/index.web.js +3 -1
- package/src/platform/patch/ali/getDefaultOptions.js +16 -3
- package/src/platform/patch/builtInKeysMap.js +2 -0
- package/src/platform/patch/react/getDefaultOptions.ios.js +31 -18
- package/src/platform/patch/web/getDefaultOptions.js +4 -2
- package/src/platform/patch/wx/getDefaultOptions.js +9 -4
- package/src/runtime/createFactory.js +3 -0
- package/src/platform/builtInMixins/directiveHelperMixin.android.js +0 -2
- package/src/platform/builtInMixins/proxyEventMixin.android.js +0 -2
- package/src/platform/builtInMixins/refsMixin.android.js +0 -2
- package/src/platform/builtInMixins/styleHelperMixin.android.js +0 -2
- package/src/platform/createApp.android.js +0 -2
- package/src/platform/patch/react/getDefaultOptions.android.js +0 -1
package/@types/global.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ declare let __mpx_mode__: 'wx' | 'ali' | 'swan' | 'qq' | 'tt' | 'web' | 'dd' | '
|
|
|
4
4
|
// declaration for mpx env
|
|
5
5
|
declare let __mpx_env__: string
|
|
6
6
|
|
|
7
|
+
declare const Mixin: WechatMiniprogram.Behavior.Constructor
|
|
8
|
+
|
|
7
9
|
// Wildcard module declarations for ?resolve case
|
|
8
10
|
declare module '*?resolve' {
|
|
9
11
|
const resourcePath: string
|
package/@types/index.d.ts
CHANGED
|
@@ -137,6 +137,11 @@ interface ComponentOpt<D extends Data, P extends Properties, C, M extends Method
|
|
|
137
137
|
|
|
138
138
|
initData?: Record<string, any>
|
|
139
139
|
|
|
140
|
+
provide?: Record<string, any> | (() => Record<string, any>)
|
|
141
|
+
inject?:
|
|
142
|
+
| { [key: string]: string | Symbol | { from?: string | Symbol; default?: any } }
|
|
143
|
+
| Array<string>
|
|
144
|
+
|
|
140
145
|
[index: string]: any
|
|
141
146
|
}
|
|
142
147
|
|
|
@@ -259,13 +264,15 @@ interface MpxConfig {
|
|
|
259
264
|
ignoreWarning: boolean | string | RegExp | ((msg: string, location: string, e: Error) => boolean)
|
|
260
265
|
ignoreProxyWhiteList: Array<string>
|
|
261
266
|
observeClassInstance: boolean | Array<AnyConstructor>
|
|
262
|
-
errorHandler: (
|
|
267
|
+
errorHandler: (msg: String, location: String, e: Error) => any | null
|
|
268
|
+
warnHandler: (msg: String, location: String, e: Error) => any | null
|
|
263
269
|
proxyEventHandler: (e: WechatMiniprogram.CustomEvent) => any | null
|
|
264
270
|
setDataHandler: (data: object, target: ComponentIns<{}, {}, {}, {}, []>) => any | null
|
|
265
271
|
forceFlushSync: boolean,
|
|
266
272
|
webRouteConfig: object,
|
|
267
273
|
webConfig: object,
|
|
268
|
-
webviewConfig
|
|
274
|
+
webviewConfig: WebviewConfig,
|
|
275
|
+
rnConfig: object,
|
|
269
276
|
}
|
|
270
277
|
|
|
271
278
|
type SupportedMode = 'wx' | 'ali' | 'qq' | 'swan' | 'tt' | 'web' | 'qa'
|
|
@@ -306,6 +313,8 @@ export interface Mpx {
|
|
|
306
313
|
|
|
307
314
|
delete: typeof del
|
|
308
315
|
|
|
316
|
+
provide: typeof provide
|
|
317
|
+
|
|
309
318
|
config: MpxConfig
|
|
310
319
|
|
|
311
320
|
i18n: {
|
|
@@ -570,6 +579,13 @@ export function onScopeDispose (fn: () => void): void
|
|
|
570
579
|
export function set<T extends object> (target: T, key: string | number, value: any): void
|
|
571
580
|
export function del<T extends object> (target: T, key: keyof T): void
|
|
572
581
|
|
|
582
|
+
// provide & inject
|
|
583
|
+
export declare function provide<T>(key: InjectionKey<T> | string | number, value: T): void;
|
|
584
|
+
export declare function inject<T>(key: InjectionKey<T> | string): T | undefined;
|
|
585
|
+
export declare function inject<T>(key: InjectionKey<T> | string, defaultValue: T, treatDefaultAsFactory?: false): T;
|
|
586
|
+
export declare function inject<T>(key: InjectionKey<T> | string, defaultValue: T | (() => T), treatDefaultAsFactory: true): T;
|
|
587
|
+
export declare interface InjectionKey<T> extends Symbol {}
|
|
588
|
+
|
|
573
589
|
// nextTick
|
|
574
590
|
export function nextTick (fn: () => any): void
|
|
575
591
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpxjs/core",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.67",
|
|
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.9.
|
|
22
|
+
"@mpxjs/utils": "^2.9.67",
|
|
23
23
|
"lodash": "^4.1.1",
|
|
24
24
|
"miniprogram-api-typings": "^3.10.0"
|
|
25
25
|
},
|
|
@@ -97,5 +97,5 @@
|
|
|
97
97
|
"url": "https://github.com/didi/mpx/issues"
|
|
98
98
|
},
|
|
99
99
|
"sideEffects": false,
|
|
100
|
-
"gitHead": "
|
|
100
|
+
"gitHead": "b23d3850c16543c5998811b8d1d8e6ee7988c0f8"
|
|
101
101
|
}
|
package/src/core/mergeOptions.js
CHANGED
|
@@ -354,7 +354,7 @@ function transformHOOKS (options) {
|
|
|
354
354
|
const componentHooksMap = makeMap(convertRule.lifecycle.component)
|
|
355
355
|
for (const key in options) {
|
|
356
356
|
// 使用Component创建page实例,页面专属生命周期&自定义方法需写在methods内部
|
|
357
|
-
if (typeof options[key] === 'function' && key !== 'dataFn' && key !== 'setup' && !componentHooksMap[key]) {
|
|
357
|
+
if (typeof options[key] === 'function' && key !== 'dataFn' && key !== 'setup' && key !== 'provide' && !componentHooksMap[key]) {
|
|
358
358
|
if (!options.methods) options.methods = {}
|
|
359
359
|
options.methods[key] = options[key]
|
|
360
360
|
delete options[key]
|
package/src/core/proxy.js
CHANGED
|
@@ -8,10 +8,12 @@ import Mpx from '../index'
|
|
|
8
8
|
import {
|
|
9
9
|
noop,
|
|
10
10
|
type,
|
|
11
|
+
isArray,
|
|
11
12
|
isFunction,
|
|
12
13
|
isObject,
|
|
13
14
|
isEmptyObject,
|
|
14
15
|
isPlainObject,
|
|
16
|
+
isWeb,
|
|
15
17
|
doGetByPath,
|
|
16
18
|
getByPath,
|
|
17
19
|
setByPath,
|
|
@@ -25,6 +27,7 @@ import {
|
|
|
25
27
|
processUndefined,
|
|
26
28
|
getFirstKey,
|
|
27
29
|
callWithErrorHandling,
|
|
30
|
+
wrapMethodsWithErrorHandling,
|
|
28
31
|
warn,
|
|
29
32
|
error,
|
|
30
33
|
getEnvObj
|
|
@@ -47,6 +50,7 @@ import {
|
|
|
47
50
|
} from './innerLifecycle'
|
|
48
51
|
import contextMap from '../dynamic/vnode/context'
|
|
49
52
|
import { getAst } from '../dynamic/astCache'
|
|
53
|
+
import { inject, provide } from '../platform/export/apiInject'
|
|
50
54
|
|
|
51
55
|
let uid = 0
|
|
52
56
|
|
|
@@ -160,11 +164,15 @@ export default class MpxProxy {
|
|
|
160
164
|
// web中BEFORECREATE钩子通过vue的beforeCreate钩子单独驱动
|
|
161
165
|
this.callHook(BEFORECREATE)
|
|
162
166
|
setCurrentInstance(this)
|
|
167
|
+
// 在 props/data 初始化之前初始化 inject
|
|
168
|
+
this.initInject()
|
|
163
169
|
this.initProps()
|
|
164
170
|
this.initSetup()
|
|
165
171
|
this.initData()
|
|
166
172
|
this.initComputed()
|
|
167
173
|
this.initWatch()
|
|
174
|
+
// 在 props/data 初始化之后初始化 provide
|
|
175
|
+
this.initProvide()
|
|
168
176
|
unsetCurrentInstance()
|
|
169
177
|
}
|
|
170
178
|
|
|
@@ -219,6 +227,16 @@ export default class MpxProxy {
|
|
|
219
227
|
// 页面/组件销毁清除上下文的缓存
|
|
220
228
|
contextMap.remove(this.uid)
|
|
221
229
|
}
|
|
230
|
+
if (!isWeb && this.options.__type__ === 'page') {
|
|
231
|
+
// 小程序页面销毁时移除对应的 provide
|
|
232
|
+
if (isFunction(this.target.getPageId)) {
|
|
233
|
+
const pageId = this.target.getPageId()
|
|
234
|
+
const providesMap = global.__mpxProvidesMap
|
|
235
|
+
if (providesMap.__pages[pageId]) {
|
|
236
|
+
delete providesMap.__pages[pageId]
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
222
240
|
this.callHook(BEFOREUNMOUNT)
|
|
223
241
|
this.scope?.stop()
|
|
224
242
|
if (this.update) this.update.active = false
|
|
@@ -277,7 +295,7 @@ export default class MpxProxy {
|
|
|
277
295
|
initSetup () {
|
|
278
296
|
const setup = this.options.setup
|
|
279
297
|
if (setup) {
|
|
280
|
-
|
|
298
|
+
let setupResult = callWithErrorHandling(setup, this, 'setup function', [
|
|
281
299
|
this.props,
|
|
282
300
|
{
|
|
283
301
|
triggerEvent: this.target.triggerEvent ? this.target.triggerEvent.bind(this.target) : noop,
|
|
@@ -294,6 +312,7 @@ export default class MpxProxy {
|
|
|
294
312
|
error(`Setup() should return a object, received: ${type(setupResult)}.`, this.options.mpxFileResource)
|
|
295
313
|
return
|
|
296
314
|
}
|
|
315
|
+
setupResult = wrapMethodsWithErrorHandling(setupResult, this)
|
|
297
316
|
proxy(this.target, setupResult, undefined, false, this.createProxyConflictHandler('setup result'))
|
|
298
317
|
this.collectLocalKeys(setupResult, (key, val) => !isFunction(val))
|
|
299
318
|
}
|
|
@@ -350,6 +369,55 @@ export default class MpxProxy {
|
|
|
350
369
|
}
|
|
351
370
|
}
|
|
352
371
|
|
|
372
|
+
initProvide () {
|
|
373
|
+
const provideOpt = this.options.provide
|
|
374
|
+
if (provideOpt) {
|
|
375
|
+
const provided = isFunction(provideOpt)
|
|
376
|
+
? callWithErrorHandling(provideOpt.bind(this.target), this, 'provide function')
|
|
377
|
+
: provideOpt
|
|
378
|
+
if (!isObject(provided)) {
|
|
379
|
+
return
|
|
380
|
+
}
|
|
381
|
+
Object.keys(provided).forEach(key => {
|
|
382
|
+
provide(key, provided[key])
|
|
383
|
+
})
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
initInject () {
|
|
388
|
+
const injectOpt = this.options.inject
|
|
389
|
+
if (injectOpt) {
|
|
390
|
+
this.resolveInject(injectOpt)
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
resolveInject (injectOpt) {
|
|
395
|
+
if (isArray(injectOpt)) {
|
|
396
|
+
const normalized = {}
|
|
397
|
+
for (let i = 0; i < injectOpt.length; i++) {
|
|
398
|
+
normalized[injectOpt[i]] = injectOpt[i]
|
|
399
|
+
}
|
|
400
|
+
injectOpt = normalized
|
|
401
|
+
}
|
|
402
|
+
const injectObj = {}
|
|
403
|
+
for (const key in injectOpt) {
|
|
404
|
+
const opt = injectOpt[key]
|
|
405
|
+
let injected
|
|
406
|
+
if (isObject(opt)) {
|
|
407
|
+
if ('default' in opt) {
|
|
408
|
+
injected = inject(opt.from || key, opt.default, true)
|
|
409
|
+
} else {
|
|
410
|
+
injected = inject(opt.from || key)
|
|
411
|
+
}
|
|
412
|
+
} else {
|
|
413
|
+
injected = inject(opt)
|
|
414
|
+
}
|
|
415
|
+
injectObj[key] = injected
|
|
416
|
+
}
|
|
417
|
+
proxy(this.target, injectObj, undefined, false, this.createProxyConflictHandler('inject'))
|
|
418
|
+
this.collectLocalKeys(injectObj)
|
|
419
|
+
}
|
|
420
|
+
|
|
353
421
|
watch (source, cb, options) {
|
|
354
422
|
const target = this.target
|
|
355
423
|
const getter = isString(source)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import transferOptions from '../core/transferOptions'
|
|
2
2
|
import builtInKeysMap from './patch/builtInKeysMap'
|
|
3
|
-
import { makeMap, spreadProp } from '@mpxjs/utils'
|
|
3
|
+
import { makeMap, spreadProp, parseUrlQuery } from '@mpxjs/utils'
|
|
4
4
|
import { mergeLifecycle } from '../convertor/mergeLifecycle'
|
|
5
5
|
import * as wxLifecycle from '../platform/patch/wx/lifecycle'
|
|
6
6
|
import Mpx from '../index'
|
|
@@ -40,7 +40,7 @@ function createAppInstance (appData) {
|
|
|
40
40
|
export default function createApp (option, config = {}) {
|
|
41
41
|
const appData = {}
|
|
42
42
|
|
|
43
|
-
const { NavigationContainer,
|
|
43
|
+
const { NavigationContainer, createStackNavigator, SafeAreaProvider } = global.__navigationHelper
|
|
44
44
|
// app选项目前不需要进行转换
|
|
45
45
|
const { rawOptions, currentInject } = transferOptions(option, 'app', false)
|
|
46
46
|
const defaultOptions = filterOptions(spreadProp(rawOptions, 'methods'), appData)
|
|
@@ -51,16 +51,25 @@ export default function createApp (option, config = {}) {
|
|
|
51
51
|
}
|
|
52
52
|
const pages = currentInject.getPages() || {}
|
|
53
53
|
const firstPage = currentInject.firstPage
|
|
54
|
-
const Stack =
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
const Stack = createStackNavigator()
|
|
55
|
+
const getPageScreens = (initialRouteName, initialParams) => {
|
|
56
|
+
return Object.entries(pages).map(([key, item]) => {
|
|
57
|
+
if (key === initialRouteName) {
|
|
58
|
+
return createElement(Stack.Screen, {
|
|
59
|
+
name: key,
|
|
60
|
+
component: item,
|
|
61
|
+
initialParams
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
return createElement(Stack.Screen, {
|
|
65
|
+
name: key,
|
|
66
|
+
component: item
|
|
67
|
+
})
|
|
60
68
|
})
|
|
61
|
-
}
|
|
69
|
+
}
|
|
62
70
|
global.__mpxOptionsMap = global.__mpxOptionsMap || {}
|
|
63
|
-
const onStateChange = () => {
|
|
71
|
+
const onStateChange = (state) => {
|
|
72
|
+
Mpx.config.rnConfig.onStateChange?.(state)
|
|
64
73
|
if (global.__navigationHelper.lastSuccessCallback) {
|
|
65
74
|
global.__navigationHelper.lastSuccessCallback()
|
|
66
75
|
global.__navigationHelper.lastSuccessCallback = null
|
|
@@ -81,26 +90,48 @@ export default function createApp (option, config = {}) {
|
|
|
81
90
|
error: []
|
|
82
91
|
}
|
|
83
92
|
|
|
93
|
+
global.__mpxAppLaunched = false
|
|
94
|
+
|
|
84
95
|
global.__mpxAppFocusedState = ref('show')
|
|
85
|
-
global.__mpxOptionsMap[currentInject.moduleId] = memo(() => {
|
|
96
|
+
global.__mpxOptionsMap[currentInject.moduleId] = memo((props) => {
|
|
86
97
|
const instanceRef = useRef(null)
|
|
87
98
|
if (!instanceRef.current) {
|
|
88
99
|
instanceRef.current = createAppInstance(appData)
|
|
89
100
|
}
|
|
90
101
|
const instance = instanceRef.current
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
102
|
+
const initialRouteRef = useRef({
|
|
103
|
+
initialRouteName: firstPage,
|
|
104
|
+
initialParams: {}
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
if (!global.__mpxAppLaunched) {
|
|
108
|
+
const parsed = Mpx.config.rnConfig.parseAppProps?.(props) || {}
|
|
109
|
+
if (parsed.url) {
|
|
110
|
+
const { path, queryObj } = parseUrlQuery(parsed.url)
|
|
111
|
+
Object.assign(initialRouteRef.current, {
|
|
112
|
+
initialRouteName: path.startsWith('/') ? path.slice(1) : path,
|
|
113
|
+
initialParams: queryObj
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
global.__mpxAppOnLaunch = (navigation) => {
|
|
117
|
+
global.__mpxAppLaunched = true
|
|
118
|
+
const state = navigation.getState()
|
|
119
|
+
Mpx.config.rnConfig.onStateChange?.(state)
|
|
120
|
+
const current = state.routes[state.index]
|
|
121
|
+
global.__mpxEnterOptions = {
|
|
122
|
+
path: current.name,
|
|
123
|
+
query: current.params,
|
|
124
|
+
scene: 0,
|
|
125
|
+
shareTicket: '',
|
|
126
|
+
referrerInfo: {}
|
|
127
|
+
}
|
|
128
|
+
defaultOptions.onLaunch && defaultOptions.onLaunch.call(instance, global.__mpxEnterOptions)
|
|
129
|
+
defaultOptions.onShow && defaultOptions.onShow.call(instance, global.__mpxEnterOptions)
|
|
99
130
|
}
|
|
100
|
-
|
|
101
|
-
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
useEffect(() => {
|
|
102
134
|
if (defaultOptions.onShow) {
|
|
103
|
-
defaultOptions.onShow.call(instance, options)
|
|
104
135
|
global.__mpxAppCbs.show.push(defaultOptions.onShow.bind(instance))
|
|
105
136
|
}
|
|
106
137
|
if (defaultOptions.onHide) {
|
|
@@ -113,7 +144,7 @@ export default function createApp (option, config = {}) {
|
|
|
113
144
|
const changeSubscription = ReactNative.AppState.addEventListener('change', (currentState) => {
|
|
114
145
|
if (currentState === 'active') {
|
|
115
146
|
global.__mpxAppCbs.show.forEach((cb) => {
|
|
116
|
-
cb(
|
|
147
|
+
cb(global.__mpxEnterOptions)
|
|
117
148
|
})
|
|
118
149
|
global.__mpxAppFocusedState.value = 'show'
|
|
119
150
|
} else if (currentState === 'inactive') {
|
|
@@ -138,19 +169,22 @@ export default function createApp (option, config = {}) {
|
|
|
138
169
|
}
|
|
139
170
|
}, [])
|
|
140
171
|
|
|
172
|
+
const { initialRouteName, initialParams } = initialRouteRef.current
|
|
141
173
|
return createElement(SafeAreaProvider,
|
|
142
174
|
null,
|
|
143
175
|
createElement(NavigationContainer,
|
|
144
176
|
{
|
|
145
|
-
ref: navigationRef,
|
|
146
177
|
onStateChange,
|
|
147
178
|
onUnhandledAction
|
|
148
179
|
},
|
|
149
180
|
createElement(Stack.Navigator,
|
|
150
181
|
{
|
|
151
|
-
initialRouteName
|
|
182
|
+
initialRouteName,
|
|
183
|
+
headerBackButtonDisplayMode: 'minimal',
|
|
184
|
+
headerMode: 'float',
|
|
185
|
+
gestureEnabled: true
|
|
152
186
|
},
|
|
153
|
-
...
|
|
187
|
+
...getPageScreens(initialRouteName, initialParams)
|
|
154
188
|
)
|
|
155
189
|
)
|
|
156
190
|
)
|
|
@@ -5,6 +5,7 @@ import { makeMap, spreadProp, isBrowser } from '@mpxjs/utils'
|
|
|
5
5
|
import { mergeLifecycle } from '../convertor/mergeLifecycle'
|
|
6
6
|
import * as webLifecycle from '../platform/patch/web/lifecycle'
|
|
7
7
|
import Mpx from '../index'
|
|
8
|
+
import { initAppProvides } from './export/apiInject'
|
|
8
9
|
|
|
9
10
|
const webAppHooksMap = makeMap(mergeLifecycle(webLifecycle.LIFECYCLE).app)
|
|
10
11
|
|
|
@@ -14,7 +15,7 @@ function filterOptions (options, appData) {
|
|
|
14
15
|
if (builtInKeysMap[key]) {
|
|
15
16
|
return
|
|
16
17
|
}
|
|
17
|
-
if (__mpx_mode__ === 'web' && !webAppHooksMap[key]) {
|
|
18
|
+
if (__mpx_mode__ === 'web' && !webAppHooksMap[key] && key !== 'provide') {
|
|
18
19
|
appData[key] = options[key]
|
|
19
20
|
} else {
|
|
20
21
|
newOptions[key] = options[key]
|
|
@@ -87,6 +88,7 @@ export default function createApp (option, config = {}) {
|
|
|
87
88
|
return appData
|
|
88
89
|
}
|
|
89
90
|
} else {
|
|
91
|
+
initAppProvides(rawOptions)
|
|
90
92
|
defaultOptions.onAppInit && defaultOptions.onAppInit()
|
|
91
93
|
const ctor = config.customCtor || global.currentCtor || App
|
|
92
94
|
ctor(defaultOptions)
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { callWithErrorHandling, isFunction, isObject, warn } from '@mpxjs/utils'
|
|
2
|
+
import { currentInstance } from '../../core/proxy'
|
|
3
|
+
|
|
4
|
+
const providesMap = {
|
|
5
|
+
/** 全局 scope */
|
|
6
|
+
__app: Object.create(null),
|
|
7
|
+
/** 页面 scope */
|
|
8
|
+
__pages: Object.create(null)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
global.__mpxProvidesMap = providesMap
|
|
12
|
+
|
|
13
|
+
/** @internal createApp() 初始化应用层 scope provide */
|
|
14
|
+
export function initAppProvides (appOptions) {
|
|
15
|
+
const provideOpt = appOptions.provide
|
|
16
|
+
if (provideOpt) {
|
|
17
|
+
const provided = isFunction(provideOpt)
|
|
18
|
+
? callWithErrorHandling(provideOpt.bind(appOptions), appOptions, 'createApp provide function')
|
|
19
|
+
: provideOpt
|
|
20
|
+
if (isObject(provided)) {
|
|
21
|
+
providesMap.__app = provided
|
|
22
|
+
} else {
|
|
23
|
+
warn('App provides must be an object or a function that returns an object.')
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function resolvePageId (context) {
|
|
29
|
+
if (context && isFunction(context.getPageId)) {
|
|
30
|
+
return context.getPageId()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function resolvePageProvides (context) {
|
|
35
|
+
const pageId = resolvePageId(context)
|
|
36
|
+
return providesMap.__pages[pageId] || (providesMap.__pages[pageId] = Object.create(null))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function provide (key, value) {
|
|
40
|
+
const instance = currentInstance
|
|
41
|
+
if (!instance) {
|
|
42
|
+
warn('provide() can only be used inside setup().')
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
// 小程序无法实现组件父级引用,所以 provide scope 设置为组件所在页面
|
|
46
|
+
const provides = resolvePageProvides(instance.target)
|
|
47
|
+
provides[key] = value
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function inject (key, defaultValue, treatDefaultAsFactory = false) {
|
|
51
|
+
const instance = currentInstance
|
|
52
|
+
if (!instance) {
|
|
53
|
+
warn('inject() can only be used inside setup()')
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
const provides = resolvePageProvides(instance.target)
|
|
57
|
+
if (key in provides) {
|
|
58
|
+
return provides[key]
|
|
59
|
+
} else if (key in providesMap.__app) {
|
|
60
|
+
return providesMap.__app[key]
|
|
61
|
+
} else if (arguments.length > 1) {
|
|
62
|
+
return treatDefaultAsFactory && isFunction(defaultValue)
|
|
63
|
+
? defaultValue.call(instance && instance.target)
|
|
64
|
+
: defaultValue
|
|
65
|
+
} else {
|
|
66
|
+
warn(`injection "${String(key)}" not found.`)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { provide, inject } from 'vue'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import MpxProxy from '../../../core/proxy'
|
|
2
2
|
import builtInKeysMap from '../builtInKeysMap'
|
|
3
3
|
import mergeOptions from '../../../core/mergeOptions'
|
|
4
|
-
import { error, diffAndCloneA, hasOwn, noop } from '@mpxjs/utils'
|
|
4
|
+
import { error, diffAndCloneA, hasOwn, noop, wrapMethodsWithErrorHandling } from '@mpxjs/utils'
|
|
5
5
|
|
|
6
6
|
function transformApiForProxy (context, currentInject) {
|
|
7
7
|
const rawSetData = context.setData.bind(context)
|
|
@@ -100,12 +100,25 @@ function filterOptions (options, type) {
|
|
|
100
100
|
if (!hasOwn(newOptions, 'props')) {
|
|
101
101
|
newOptions.props = Object.assign({}, options.props, options.properties)
|
|
102
102
|
}
|
|
103
|
-
} else if (key === 'methods'
|
|
104
|
-
|
|
103
|
+
} else if (key === 'methods') {
|
|
104
|
+
const newMethods = wrapMethodsWithErrorHandling(options[key])
|
|
105
|
+
if (type === 'page') {
|
|
106
|
+
// 构造器为Page时抽取所有methods方法到顶层
|
|
107
|
+
Object.assign(newOptions, newMethods)
|
|
108
|
+
} else {
|
|
109
|
+
newOptions[key] = newMethods
|
|
110
|
+
}
|
|
111
|
+
} else if (key === 'behaviors') {
|
|
112
|
+
newOptions.mixins = options[key]
|
|
105
113
|
} else {
|
|
106
114
|
newOptions[key] = options[key]
|
|
107
115
|
}
|
|
108
116
|
})
|
|
117
|
+
if (newOptions.relations) {
|
|
118
|
+
// ali relations 需要设置 options.relations = true
|
|
119
|
+
newOptions.options = newOptions.options || {}
|
|
120
|
+
newOptions.options.relations = true
|
|
121
|
+
}
|
|
109
122
|
return newOptions
|
|
110
123
|
}
|
|
111
124
|
|
|
@@ -3,7 +3,7 @@ import * as ReactNative from 'react-native'
|
|
|
3
3
|
import { ReactiveEffect } from '../../../observer/effect'
|
|
4
4
|
import { watch } from '../../../observer/watch'
|
|
5
5
|
import { reactive, set, del } from '../../../observer/reactive'
|
|
6
|
-
import { hasOwn, isFunction, noop, isObject, getByPath, collectDataset, hump2dash } from '@mpxjs/utils'
|
|
6
|
+
import { hasOwn, isFunction, noop, isObject, getByPath, collectDataset, hump2dash, wrapMethodsWithErrorHandling } 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'
|
|
@@ -347,6 +347,7 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
347
347
|
rawOptions = mergeOptions(rawOptions, type, false)
|
|
348
348
|
const components = Object.assign({}, rawOptions.components, currentInject.getComponents())
|
|
349
349
|
const validProps = Object.assign({}, rawOptions.props, rawOptions.properties)
|
|
350
|
+
if (rawOptions.methods) rawOptions.methods = wrapMethodsWithErrorHandling(rawOptions.methods)
|
|
350
351
|
const defaultOptions = memo(forwardRef((props, ref) => {
|
|
351
352
|
const instanceRef = useRef(null)
|
|
352
353
|
const propsRef = useRef(null)
|
|
@@ -365,7 +366,21 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
365
366
|
|
|
366
367
|
const proxy = instance.__mpxProxy
|
|
367
368
|
|
|
368
|
-
proxy.callHook(REACTHOOKSEXEC)
|
|
369
|
+
let hooksResult = proxy.callHook(REACTHOOKSEXEC, [props])
|
|
370
|
+
if (isObject(hooksResult)) {
|
|
371
|
+
hooksResult = wrapMethodsWithErrorHandling(hooksResult, proxy)
|
|
372
|
+
if (isFirst) {
|
|
373
|
+
const onConflict = proxy.createProxyConflictHandler('react hooks result')
|
|
374
|
+
Object.keys(hooksResult).forEach((key) => {
|
|
375
|
+
if (key in proxy.target) {
|
|
376
|
+
onConflict(key)
|
|
377
|
+
}
|
|
378
|
+
proxy.target[key] = hooksResult[key]
|
|
379
|
+
})
|
|
380
|
+
} else {
|
|
381
|
+
Object.assign(proxy.target, hooksResult)
|
|
382
|
+
}
|
|
383
|
+
}
|
|
369
384
|
|
|
370
385
|
useEffect(() => {
|
|
371
386
|
if (!isFirst) {
|
|
@@ -391,6 +406,9 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
391
406
|
|
|
392
407
|
useEffect(() => {
|
|
393
408
|
if (type === 'page') {
|
|
409
|
+
if (!global.__mpxAppLaunched && global.__mpxAppOnLaunch) {
|
|
410
|
+
global.__mpxAppOnLaunch(props.navigation)
|
|
411
|
+
}
|
|
394
412
|
proxy.callHook(ONLOAD, [props.route.params || {}])
|
|
395
413
|
}
|
|
396
414
|
proxy.mounted()
|
|
@@ -429,26 +447,21 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
429
447
|
|
|
430
448
|
useLayoutEffect(() => {
|
|
431
449
|
const isCustom = pageConfig.navigationStyle === 'custom'
|
|
432
|
-
|
|
450
|
+
const opt = {}
|
|
433
451
|
if (__mpx_mode__ === 'android') {
|
|
434
|
-
opt = {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
}
|
|
439
|
-
} else if (__mpx_mode__ === 'ios') {
|
|
440
|
-
opt = {
|
|
441
|
-
headerBackTitleVisible: false
|
|
442
|
-
}
|
|
452
|
+
// opt = {
|
|
453
|
+
// statusBarTranslucent: isCustom,
|
|
454
|
+
// statusBarStyle: pageConfig.statusBarStyle, // 枚举值 'auto' | 'dark' | 'light' 控制statusbar字体颜色
|
|
455
|
+
// statusBarColor: isCustom ? 'transparent' : pageConfig.statusBarColor // 控制statusbar背景颜色
|
|
456
|
+
// }
|
|
443
457
|
}
|
|
444
458
|
navigation.setOptions({
|
|
445
459
|
headerShown: !isCustom,
|
|
446
|
-
|
|
447
|
-
headerTitle: pageConfig.navigationBarTitleText || '',
|
|
460
|
+
title: pageConfig.navigationBarTitleText || '',
|
|
448
461
|
headerStyle: {
|
|
449
462
|
backgroundColor: pageConfig.navigationBarBackgroundColor || '#000000'
|
|
450
463
|
},
|
|
451
|
-
headerTitleAlign: 'center',
|
|
464
|
+
// headerTitleAlign: 'center',
|
|
452
465
|
headerTintColor: pageConfig.navigationBarTextStyle || 'white',
|
|
453
466
|
...opt
|
|
454
467
|
})
|
|
@@ -484,9 +497,9 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
484
497
|
value: currentPageId
|
|
485
498
|
},
|
|
486
499
|
createElement(IntersectionObserverContext.Provider,
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
500
|
+
{
|
|
501
|
+
value: intersectionObservers.current
|
|
502
|
+
},
|
|
490
503
|
createElement(defaultOptions,
|
|
491
504
|
{
|
|
492
505
|
navigation,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import builtInKeysMap from '../builtInKeysMap'
|
|
2
2
|
import mergeOptions from '../../../core/mergeOptions'
|
|
3
|
-
import { diffAndCloneA, hasOwn } from '@mpxjs/utils'
|
|
3
|
+
import { diffAndCloneA, hasOwn, wrapMethodsWithErrorHandling } from '@mpxjs/utils'
|
|
4
4
|
import { getCurrentInstance as getCurrentVueInstance } from '../../export/index'
|
|
5
5
|
import MpxProxy, { setCurrentInstance, unsetCurrentInstance } from '../../../core/proxy'
|
|
6
6
|
import {
|
|
@@ -27,6 +27,8 @@ function filterOptions (options) {
|
|
|
27
27
|
)
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
} else if (key === 'methods') {
|
|
31
|
+
newOptions[key] = wrapMethodsWithErrorHandling(options[key])
|
|
30
32
|
} else {
|
|
31
33
|
newOptions[key] = options[key]
|
|
32
34
|
}
|
|
@@ -62,7 +64,7 @@ export function getDefaultOptions ({ type, rawOptions = {} }) {
|
|
|
62
64
|
}
|
|
63
65
|
const setupRes = rawSetup(props, newContext)
|
|
64
66
|
unsetCurrentInstance(instance.__mpxProxy)
|
|
65
|
-
return setupRes
|
|
67
|
+
return wrapMethodsWithErrorHandling(setupRes, instance.__mpxProxy)
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
70
|
const rootMixins = [{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { hasOwn, noop, isFunction } from '@mpxjs/utils'
|
|
1
|
+
import { hasOwn, noop, isFunction, wrapMethodsWithErrorHandling } from '@mpxjs/utils'
|
|
2
2
|
import MpxProxy from '../../../core/proxy'
|
|
3
3
|
import builtInKeysMap from '../builtInKeysMap'
|
|
4
4
|
import mergeOptions from '../../../core/mergeOptions'
|
|
@@ -140,9 +140,14 @@ export function filterOptions (options) {
|
|
|
140
140
|
if (!hasOwn(newOptions, 'properties')) {
|
|
141
141
|
newOptions.properties = transformProperties(Object.assign({}, options.props, options.properties))
|
|
142
142
|
}
|
|
143
|
-
} else if (key === 'methods'
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
} else if (key === 'methods') {
|
|
144
|
+
const newMethods = wrapMethodsWithErrorHandling(options[key])
|
|
145
|
+
if (options.__pageCtor__) {
|
|
146
|
+
// 构造器为Page时抽取所有methods方法到顶层
|
|
147
|
+
Object.assign(newOptions, newMethods)
|
|
148
|
+
} else {
|
|
149
|
+
newOptions[key] = newMethods
|
|
150
|
+
}
|
|
146
151
|
} else {
|
|
147
152
|
newOptions[key] = options[key]
|
|
148
153
|
}
|
|
@@ -6,6 +6,9 @@ const factoryMap = {
|
|
|
6
6
|
|
|
7
7
|
module.exports = (type) => (...args) => {
|
|
8
8
|
if (type === 'Behavior') {
|
|
9
|
+
if (__mpx_mode__ === 'ali') {
|
|
10
|
+
return Mixin.apply(null, args)
|
|
11
|
+
}
|
|
9
12
|
if (args[0]) {
|
|
10
13
|
Object.defineProperty(args[0], '__mpx_behaviors_to_mixins__', {
|
|
11
14
|
configurable: true,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { getDefaultOptions } from './getDefaultOptions.ios'
|