@mpxjs/core 2.9.65 → 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 +93 -4
- package/src/platform/builtInMixins/styleHelperMixin.ios.js +3 -2
- 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 -1
- package/src/platform/export/index.web.js +3 -1
- package/src/platform/patch/ali/getDefaultOptions.js +16 -3
- package/src/platform/patch/builtInKeysMap.js +4 -0
- package/src/platform/patch/react/getDefaultOptions.ios.js +73 -39
- package/src/platform/patch/web/getDefaultOptions.js +4 -2
- package/src/platform/patch/wx/getDefaultOptions.js +12 -5
- 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
|
|
|
@@ -106,6 +110,7 @@ export default class MpxProxy {
|
|
|
106
110
|
this.uid = uid++
|
|
107
111
|
this.name = options.name || ''
|
|
108
112
|
this.options = options
|
|
113
|
+
this.ignoreReactivePattern = this.options.options?.ignoreReactivePattern
|
|
109
114
|
// beforeCreate -> created -> mounted -> unmounted
|
|
110
115
|
this.state = BEFORECREATE
|
|
111
116
|
this.ignoreProxyMap = makeMap(Mpx.config.ignoreProxyWhiteList)
|
|
@@ -135,6 +140,21 @@ export default class MpxProxy {
|
|
|
135
140
|
this.initApi()
|
|
136
141
|
}
|
|
137
142
|
|
|
143
|
+
processIgnoreReactive (obj) {
|
|
144
|
+
if (this.ignoreReactivePattern && isObject(obj)) {
|
|
145
|
+
Object.keys(obj).forEach((key) => {
|
|
146
|
+
if (this.ignoreReactivePattern.test(key)) {
|
|
147
|
+
Object.defineProperty(obj, key, {
|
|
148
|
+
enumerable: true,
|
|
149
|
+
// set configurable to false to skip defineReactive
|
|
150
|
+
configurable: false
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
return obj
|
|
156
|
+
}
|
|
157
|
+
|
|
138
158
|
created () {
|
|
139
159
|
if (__mpx_dynamic_runtime__) {
|
|
140
160
|
// 缓存上下文,在 destoryed 阶段删除
|
|
@@ -144,11 +164,15 @@ export default class MpxProxy {
|
|
|
144
164
|
// web中BEFORECREATE钩子通过vue的beforeCreate钩子单独驱动
|
|
145
165
|
this.callHook(BEFORECREATE)
|
|
146
166
|
setCurrentInstance(this)
|
|
167
|
+
// 在 props/data 初始化之前初始化 inject
|
|
168
|
+
this.initInject()
|
|
147
169
|
this.initProps()
|
|
148
170
|
this.initSetup()
|
|
149
171
|
this.initData()
|
|
150
172
|
this.initComputed()
|
|
151
173
|
this.initWatch()
|
|
174
|
+
// 在 props/data 初始化之后初始化 provide
|
|
175
|
+
this.initProvide()
|
|
152
176
|
unsetCurrentInstance()
|
|
153
177
|
}
|
|
154
178
|
|
|
@@ -203,11 +227,26 @@ export default class MpxProxy {
|
|
|
203
227
|
// 页面/组件销毁清除上下文的缓存
|
|
204
228
|
contextMap.remove(this.uid)
|
|
205
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
|
+
}
|
|
206
240
|
this.callHook(BEFOREUNMOUNT)
|
|
207
241
|
this.scope?.stop()
|
|
208
242
|
if (this.update) this.update.active = false
|
|
209
243
|
this.callHook(UNMOUNTED)
|
|
210
244
|
this.state = UNMOUNTED
|
|
245
|
+
if (this._intersectionObservers) {
|
|
246
|
+
this._intersectionObservers.forEach((observer) => {
|
|
247
|
+
observer.disconnect()
|
|
248
|
+
})
|
|
249
|
+
}
|
|
211
250
|
}
|
|
212
251
|
|
|
213
252
|
isUnmounted () {
|
|
@@ -249,14 +288,14 @@ export default class MpxProxy {
|
|
|
249
288
|
} else {
|
|
250
289
|
this.props = diffAndCloneA(this.target.__getProps(this.options)).clone
|
|
251
290
|
}
|
|
252
|
-
reactive(this.props)
|
|
291
|
+
reactive(this.processIgnoreReactive(this.props))
|
|
253
292
|
proxy(this.target, this.props, undefined, false, this.createProxyConflictHandler('props'))
|
|
254
293
|
}
|
|
255
294
|
|
|
256
295
|
initSetup () {
|
|
257
296
|
const setup = this.options.setup
|
|
258
297
|
if (setup) {
|
|
259
|
-
|
|
298
|
+
let setupResult = callWithErrorHandling(setup, this, 'setup function', [
|
|
260
299
|
this.props,
|
|
261
300
|
{
|
|
262
301
|
triggerEvent: this.target.triggerEvent ? this.target.triggerEvent.bind(this.target) : noop,
|
|
@@ -273,6 +312,7 @@ export default class MpxProxy {
|
|
|
273
312
|
error(`Setup() should return a object, received: ${type(setupResult)}.`, this.options.mpxFileResource)
|
|
274
313
|
return
|
|
275
314
|
}
|
|
315
|
+
setupResult = wrapMethodsWithErrorHandling(setupResult, this)
|
|
276
316
|
proxy(this.target, setupResult, undefined, false, this.createProxyConflictHandler('setup result'))
|
|
277
317
|
this.collectLocalKeys(setupResult, (key, val) => !isFunction(val))
|
|
278
318
|
}
|
|
@@ -287,7 +327,7 @@ export default class MpxProxy {
|
|
|
287
327
|
if (isFunction(dataFn)) {
|
|
288
328
|
Object.assign(this.data, callWithErrorHandling(dataFn.bind(this.target), this, 'data function'))
|
|
289
329
|
}
|
|
290
|
-
reactive(this.data)
|
|
330
|
+
reactive(this.processIgnoreReactive(this.data))
|
|
291
331
|
proxy(this.target, this.data, undefined, false, this.createProxyConflictHandler('data'))
|
|
292
332
|
this.collectLocalKeys(this.data)
|
|
293
333
|
}
|
|
@@ -329,6 +369,55 @@ export default class MpxProxy {
|
|
|
329
369
|
}
|
|
330
370
|
}
|
|
331
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
|
+
|
|
332
421
|
watch (source, cb, options) {
|
|
333
422
|
const target = this.target
|
|
334
423
|
const getter = isString(source)
|
|
@@ -419,7 +508,7 @@ export default class MpxProxy {
|
|
|
419
508
|
if (hasOwn(renderData, key)) {
|
|
420
509
|
const data = renderData[key]
|
|
421
510
|
const firstKey = getFirstKey(key)
|
|
422
|
-
if (!this.localKeysMap[firstKey]) {
|
|
511
|
+
if (!this.localKeysMap[firstKey] || (this.ignoreReactivePattern && this.ignoreReactivePattern.test(firstKey))) {
|
|
423
512
|
continue
|
|
424
513
|
}
|
|
425
514
|
// 外部clone,用于只需要clone的场景
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isObject, isArray, dash2hump, isFunction, cached } from '@mpxjs/utils'
|
|
1
|
+
import { isObject, isArray, dash2hump, isFunction, cached, getFocusedNavigation } from '@mpxjs/utils'
|
|
2
2
|
import { Dimensions, StyleSheet } from 'react-native'
|
|
3
3
|
|
|
4
4
|
function rpx (value) {
|
|
@@ -12,7 +12,8 @@ function vw (value) {
|
|
|
12
12
|
return value * width / 100
|
|
13
13
|
}
|
|
14
14
|
function vh (value) {
|
|
15
|
-
const
|
|
15
|
+
const navigation = getFocusedNavigation()
|
|
16
|
+
const height = navigation?.layout?.height || Dimensions.get('screen').height
|
|
16
17
|
return value * height / 100
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -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
|
|
|
@@ -7,6 +7,7 @@ if (__mpx_mode__ === 'web') {
|
|
|
7
7
|
builtInKeys = [
|
|
8
8
|
'proto',
|
|
9
9
|
'mixins',
|
|
10
|
+
'initData',
|
|
10
11
|
'mpxCustomKeysForBlend',
|
|
11
12
|
'mpxConvertMode',
|
|
12
13
|
'mpxFileResource',
|
|
@@ -20,8 +21,11 @@ if (__mpx_mode__ === 'web') {
|
|
|
20
21
|
'dataFn',
|
|
21
22
|
'proto',
|
|
22
23
|
'mixins',
|
|
24
|
+
'initData',
|
|
23
25
|
'watch',
|
|
24
26
|
'computed',
|
|
27
|
+
'provide',
|
|
28
|
+
'inject',
|
|
25
29
|
'mpxCustomKeysForBlend',
|
|
26
30
|
'mpxConvertMode',
|
|
27
31
|
'mpxFileResource',
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, createElement, memo, forwardRef, useImperativeHandle, useContext, createContext, Fragment, cloneElement } from 'react'
|
|
1
|
+
import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, useCallback, createElement, memo, forwardRef, useImperativeHandle, useContext, createContext, Fragment, cloneElement } from 'react'
|
|
2
2
|
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,
|
|
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'
|
|
10
10
|
import { queueJob } from '../../../observer/scheduler'
|
|
11
|
-
import { createSelectorQuery } from '@mpxjs/api-proxy'
|
|
11
|
+
import { createSelectorQuery, createIntersectionObserver } from '@mpxjs/api-proxy'
|
|
12
|
+
import { IntersectionObserverContext } from '@mpxjs/webpack-plugin/lib/runtime/components/react/dist/context'
|
|
12
13
|
|
|
13
14
|
function getSystemInfo () {
|
|
14
15
|
const window = ReactNative.Dimensions.get('window')
|
|
@@ -68,7 +69,7 @@ function getRootProps (props) {
|
|
|
68
69
|
return rootProps
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
function createInstance ({ propsRef, type, rawOptions, currentInject, validProps, components, pageId }) {
|
|
72
|
+
function createInstance ({ propsRef, type, rawOptions, currentInject, validProps, components, pageId, intersectionCtx }) {
|
|
72
73
|
const instance = Object.create({
|
|
73
74
|
setData (data, callback) {
|
|
74
75
|
return this.__mpxProxy.forceUpdate(data, { sync: true }, callback)
|
|
@@ -183,8 +184,8 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
|
|
|
183
184
|
createSelectorQuery () {
|
|
184
185
|
return createSelectorQuery().in(this)
|
|
185
186
|
},
|
|
186
|
-
createIntersectionObserver () {
|
|
187
|
-
|
|
187
|
+
createIntersectionObserver (opt) {
|
|
188
|
+
return createIntersectionObserver(this, opt, intersectionCtx)
|
|
188
189
|
},
|
|
189
190
|
...rawOptions.methods
|
|
190
191
|
}, {
|
|
@@ -346,15 +347,17 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
346
347
|
rawOptions = mergeOptions(rawOptions, type, false)
|
|
347
348
|
const components = Object.assign({}, rawOptions.components, currentInject.getComponents())
|
|
348
349
|
const validProps = Object.assign({}, rawOptions.props, rawOptions.properties)
|
|
350
|
+
if (rawOptions.methods) rawOptions.methods = wrapMethodsWithErrorHandling(rawOptions.methods)
|
|
349
351
|
const defaultOptions = memo(forwardRef((props, ref) => {
|
|
350
352
|
const instanceRef = useRef(null)
|
|
351
353
|
const propsRef = useRef(null)
|
|
354
|
+
const intersectionCtx = useContext(IntersectionObserverContext)
|
|
352
355
|
const pageId = useContext(RouteContext)
|
|
353
356
|
propsRef.current = props
|
|
354
357
|
let isFirst = false
|
|
355
358
|
if (!instanceRef.current) {
|
|
356
359
|
isFirst = true
|
|
357
|
-
instanceRef.current = createInstance({ propsRef, type, rawOptions, currentInject, validProps, components, pageId })
|
|
360
|
+
instanceRef.current = createInstance({ propsRef, type, rawOptions, currentInject, validProps, components, pageId, intersectionCtx })
|
|
358
361
|
}
|
|
359
362
|
const instance = instanceRef.current
|
|
360
363
|
useImperativeHandle(ref, () => {
|
|
@@ -363,7 +366,21 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
363
366
|
|
|
364
367
|
const proxy = instance.__mpxProxy
|
|
365
368
|
|
|
366
|
-
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
|
+
}
|
|
367
384
|
|
|
368
385
|
useEffect(() => {
|
|
369
386
|
if (!isFirst) {
|
|
@@ -389,6 +406,9 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
389
406
|
|
|
390
407
|
useEffect(() => {
|
|
391
408
|
if (type === 'page') {
|
|
409
|
+
if (!global.__mpxAppLaunched && global.__mpxAppOnLaunch) {
|
|
410
|
+
global.__mpxAppOnLaunch(props.navigation)
|
|
411
|
+
}
|
|
392
412
|
proxy.callHook(ONLOAD, [props.route.params || {}])
|
|
393
413
|
}
|
|
394
414
|
proxy.mounted()
|
|
@@ -413,74 +433,88 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
|
|
|
413
433
|
return root
|
|
414
434
|
}))
|
|
415
435
|
|
|
436
|
+
if (rawOptions.options?.isCustomText) {
|
|
437
|
+
defaultOptions.isCustomText = true
|
|
438
|
+
}
|
|
439
|
+
|
|
416
440
|
if (type === 'page') {
|
|
417
441
|
const { Provider, useSafeAreaInsets, GestureHandlerRootView } = global.__navigationHelper
|
|
418
442
|
const pageConfig = Object.assign({}, global.__mpxPageConfig, currentInject.pageConfig)
|
|
419
443
|
const Page = ({ navigation, route }) => {
|
|
420
|
-
const rootRef = useRef(null)
|
|
421
444
|
const currentPageId = useMemo(() => ++pageId, [])
|
|
445
|
+
const intersectionObservers = useRef({})
|
|
422
446
|
usePageStatus(navigation, currentPageId)
|
|
423
447
|
|
|
424
448
|
useLayoutEffect(() => {
|
|
425
|
-
rootRef.current?.measureInWindow((x, y, width, height) => {
|
|
426
|
-
navigation.layout = { x, y, width, height }
|
|
427
|
-
})
|
|
428
449
|
const isCustom = pageConfig.navigationStyle === 'custom'
|
|
429
|
-
|
|
450
|
+
const opt = {}
|
|
430
451
|
if (__mpx_mode__ === 'android') {
|
|
431
|
-
opt = {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
}
|
|
436
|
-
} else if (__mpx_mode__ === 'ios') {
|
|
437
|
-
opt = {
|
|
438
|
-
headerBackTitleVisible: false
|
|
439
|
-
}
|
|
452
|
+
// opt = {
|
|
453
|
+
// statusBarTranslucent: isCustom,
|
|
454
|
+
// statusBarStyle: pageConfig.statusBarStyle, // 枚举值 'auto' | 'dark' | 'light' 控制statusbar字体颜色
|
|
455
|
+
// statusBarColor: isCustom ? 'transparent' : pageConfig.statusBarColor // 控制statusbar背景颜色
|
|
456
|
+
// }
|
|
440
457
|
}
|
|
441
458
|
navigation.setOptions({
|
|
442
459
|
headerShown: !isCustom,
|
|
443
|
-
|
|
444
|
-
headerTitle: pageConfig.navigationBarTitleText || '',
|
|
460
|
+
title: pageConfig.navigationBarTitleText || '',
|
|
445
461
|
headerStyle: {
|
|
446
462
|
backgroundColor: pageConfig.navigationBarBackgroundColor || '#000000'
|
|
447
463
|
},
|
|
448
|
-
headerTitleAlign: 'center',
|
|
464
|
+
// headerTitleAlign: 'center',
|
|
449
465
|
headerTintColor: pageConfig.navigationBarTextStyle || 'white',
|
|
450
466
|
...opt
|
|
451
467
|
})
|
|
452
468
|
}, [])
|
|
453
469
|
|
|
470
|
+
const rootRef = useRef(null)
|
|
471
|
+
const onLayout = useCallback(() => {
|
|
472
|
+
rootRef.current?.measureInWindow((x, y, width, height) => {
|
|
473
|
+
navigation.layout = { x, y, width, height }
|
|
474
|
+
})
|
|
475
|
+
}, [])
|
|
476
|
+
|
|
454
477
|
navigation.insets = useSafeAreaInsets()
|
|
455
478
|
|
|
456
479
|
return createElement(GestureHandlerRootView,
|
|
457
480
|
{
|
|
481
|
+
style: {
|
|
482
|
+
flex: 1
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
createElement(ReactNative.View, {
|
|
458
486
|
style: {
|
|
459
487
|
flex: 1,
|
|
460
488
|
backgroundColor: pageConfig.backgroundColor || '#ffffff'
|
|
461
489
|
},
|
|
462
|
-
ref: rootRef
|
|
490
|
+
ref: rootRef,
|
|
491
|
+
onLayout
|
|
463
492
|
},
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
createElement(RouteContext.Provider,
|
|
468
|
-
{
|
|
469
|
-
value: currentPageId
|
|
470
|
-
},
|
|
471
|
-
createElement(defaultOptions,
|
|
493
|
+
createElement(Provider,
|
|
494
|
+
null,
|
|
495
|
+
createElement(RouteContext.Provider,
|
|
472
496
|
{
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
497
|
+
value: currentPageId
|
|
498
|
+
},
|
|
499
|
+
createElement(IntersectionObserverContext.Provider,
|
|
500
|
+
{
|
|
501
|
+
value: intersectionObservers.current
|
|
502
|
+
},
|
|
503
|
+
createElement(defaultOptions,
|
|
504
|
+
{
|
|
505
|
+
navigation,
|
|
506
|
+
route,
|
|
507
|
+
id: currentPageId
|
|
508
|
+
}
|
|
509
|
+
)
|
|
510
|
+
)
|
|
477
511
|
)
|
|
478
512
|
)
|
|
479
513
|
)
|
|
514
|
+
// todo custom portal host for active route
|
|
480
515
|
)
|
|
481
516
|
}
|
|
482
517
|
return Page
|
|
483
518
|
}
|
|
484
|
-
|
|
485
519
|
return defaultOptions
|
|
486
520
|
}
|
|
@@ -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'
|
|
@@ -23,11 +23,13 @@ function transformProperties (properties) {
|
|
|
23
23
|
} else {
|
|
24
24
|
newFiled = Object.assign({}, rawFiled)
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
const rawObserver = rawFiled?.observer
|
|
27
|
+
newFiled.observer = function (value, oldValue) {
|
|
27
28
|
if (this.__mpxProxy) {
|
|
28
29
|
this[key] = value
|
|
29
30
|
this.__mpxProxy.propsUpdated()
|
|
30
31
|
}
|
|
32
|
+
rawObserver && rawObserver.call(this, value, oldValue)
|
|
31
33
|
}
|
|
32
34
|
newProps[key] = newFiled
|
|
33
35
|
})
|
|
@@ -138,9 +140,14 @@ export function filterOptions (options) {
|
|
|
138
140
|
if (!hasOwn(newOptions, 'properties')) {
|
|
139
141
|
newOptions.properties = transformProperties(Object.assign({}, options.props, options.properties))
|
|
140
142
|
}
|
|
141
|
-
} else if (key === 'methods'
|
|
142
|
-
|
|
143
|
-
|
|
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
|
+
}
|
|
144
151
|
} else {
|
|
145
152
|
newOptions[key] = options[key]
|
|
146
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'
|