@mpxjs/core 2.9.66 → 2.9.69-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/@types/global.d.ts +2 -0
- package/@types/index.d.ts +18 -2
- package/package.json +19 -7
- package/src/convertor/convertor.js +11 -32
- package/src/convertor/wxToAli.js +3 -3
- package/src/convertor/wxToReact.js +1 -1
- package/src/convertor/wxToSwan.js +3 -3
- package/src/convertor/wxToWeb.js +3 -3
- package/src/core/mergeOptions.js +1 -1
- package/src/core/proxy.js +86 -12
- package/src/dynamic/dynamicRenderMixin.js +2 -2
- package/src/index.js +3 -14
- package/src/observer/reactive.js +5 -4
- package/src/observer/ref.js +3 -2
- package/src/observer/scheduler.js +4 -0
- package/src/observer/watch.js +5 -4
- package/src/platform/builtInMixins/directiveHelperMixin.ios.js +4 -1
- package/src/platform/builtInMixins/styleHelperMixin.ios.js +28 -25
- package/src/platform/createApp.ios.js +110 -42
- package/src/platform/createApp.js +8 -8
- package/src/platform/env/event.js +108 -0
- package/src/platform/env/index.ios.js +51 -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 +1 -1
- package/src/platform/export/index.js +5 -0
- package/src/platform/export/index.web.js +3 -1
- package/src/platform/export/inject.js +68 -0
- package/src/platform/export/inject.web.js +1 -0
- package/src/platform/patch/builtInKeysMap.js +2 -0
- package/src/platform/patch/{ali/getDefaultOptions.js → getDefaultOptions.ali.js} +19 -6
- package/src/platform/patch/{react/getDefaultOptions.ios.js → getDefaultOptions.ios.js} +286 -200
- package/src/platform/patch/{wx/getDefaultOptions.js → getDefaultOptions.js} +20 -11
- package/src/platform/patch/{web/getDefaultOptions.js → getDefaultOptions.web.js} +9 -7
- package/src/platform/patch/index.js +4 -21
- package/src/platform/patch/{ali/lifecycle.js → lifecycle/index.ali.js} +2 -0
- package/src/platform/patch/lifecycle/index.js +1 -0
- package/src/platform/patch/{swan/lifecycle.js → lifecycle/index.swan.js} +2 -0
- package/src/platform/patch/{web/lifecycle.js → lifecycle/index.web.js} +4 -0
- package/src/platform/patch/{wx/lifecycle.js → lifecycle/index.wx.js} +2 -0
- package/src/runtime/createFactory.js +3 -0
- package/LICENSE +0 -433
- package/src/external/vue.js +0 -1
- package/src/external/vue.web.js +0 -6
- 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/src/platform/patch/react/getDefaultOptions.js +0 -1
- package/src/platform/patch/swan/getDefaultOptions.js +0 -34
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import { isObject, isArray, dash2hump,
|
|
1
|
+
import { isObject, isArray, dash2hump, cached, isEmptyObject } from '@mpxjs/utils'
|
|
2
2
|
import { Dimensions, StyleSheet } from 'react-native'
|
|
3
3
|
|
|
4
|
+
let { width, height } = Dimensions.get('screen')
|
|
5
|
+
|
|
6
|
+
Dimensions.addEventListener('change', ({ screen }) => {
|
|
7
|
+
width = screen.width
|
|
8
|
+
height = screen.height
|
|
9
|
+
})
|
|
10
|
+
|
|
4
11
|
function rpx (value) {
|
|
5
|
-
const { width } = Dimensions.get('screen')
|
|
6
12
|
// rn 单位 dp = 1(css)px = 1 物理像素 * pixelRatio(像素比)
|
|
7
13
|
// px = rpx * (750 / 屏幕宽度)
|
|
8
14
|
return value * width / 750
|
|
9
15
|
}
|
|
10
16
|
function vw (value) {
|
|
11
|
-
const { width } = Dimensions.get('screen')
|
|
12
17
|
return value * width / 100
|
|
13
18
|
}
|
|
14
19
|
function vh (value) {
|
|
15
|
-
const navigation = getFocusedNavigation()
|
|
16
|
-
const height = navigation?.layout?.height || Dimensions.get('screen').height
|
|
17
20
|
return value * height / 100
|
|
18
21
|
}
|
|
19
22
|
|
|
@@ -23,15 +26,18 @@ const unit = {
|
|
|
23
26
|
vh
|
|
24
27
|
}
|
|
25
28
|
|
|
29
|
+
const empty = {}
|
|
30
|
+
|
|
26
31
|
function formatValue (value) {
|
|
27
|
-
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
const matched = unitRegExp.exec(value)
|
|
33
|
+
if (matched) {
|
|
34
|
+
if (!matched[2] || matched[2] === 'px') {
|
|
35
|
+
return +matched[1]
|
|
36
|
+
} else {
|
|
37
|
+
return unit[matched[2]](+matched[1])
|
|
38
|
+
}
|
|
34
39
|
}
|
|
40
|
+
if (hairlineRegExp.test(value)) return StyleSheet.hairlineWidth
|
|
35
41
|
return value
|
|
36
42
|
}
|
|
37
43
|
|
|
@@ -106,8 +112,7 @@ function stringifyDynamicClass (value) {
|
|
|
106
112
|
|
|
107
113
|
const listDelimiter = /;(?![^(]*[)])/g
|
|
108
114
|
const propertyDelimiter = /:(.+)/
|
|
109
|
-
const unitRegExp = /^\s*(-?\d+(?:\.\d+)?)(rpx|vw|vh)
|
|
110
|
-
const numberRegExp = /^\s*(-?\d+(\.\d+)?)(px)?\s*$/
|
|
115
|
+
const unitRegExp = /^\s*(-?\d+(?:\.\d+)?)(rpx|vw|vh|px)?\s*$/
|
|
111
116
|
const hairlineRegExp = /^\s*hairlineWidth\s*$/
|
|
112
117
|
const varRegExp = /^--/
|
|
113
118
|
|
|
@@ -164,14 +169,8 @@ export default function styleHelperMixin () {
|
|
|
164
169
|
},
|
|
165
170
|
__getStyle (staticClass, dynamicClass, staticStyle, dynamicStyle, hide) {
|
|
166
171
|
const result = {}
|
|
167
|
-
const classMap = {}
|
|
168
|
-
|
|
169
|
-
if (isFunction(global.__getAppClassMap)) {
|
|
170
|
-
Object.assign(classMap, global.__getAppClassMap())
|
|
171
|
-
}
|
|
172
|
-
if (isFunction(this.__getClassMap)) {
|
|
173
|
-
Object.assign(classMap, this.__getClassMap())
|
|
174
|
-
}
|
|
172
|
+
const classMap = this.__getClassMap?.() || {}
|
|
173
|
+
const appClassMap = global.__getAppClassMap?.() || {}
|
|
175
174
|
|
|
176
175
|
if (staticClass || dynamicClass) {
|
|
177
176
|
// todo 当前为了复用小程序unocss产物,暂时进行mpEscape,等后续正式支持unocss后可不进行mpEscape
|
|
@@ -179,9 +178,12 @@ export default function styleHelperMixin () {
|
|
|
179
178
|
classString.split(/\s+/).forEach((className) => {
|
|
180
179
|
if (classMap[className]) {
|
|
181
180
|
Object.assign(result, classMap[className])
|
|
182
|
-
} else if (
|
|
181
|
+
} else if (appClassMap[className]) {
|
|
182
|
+
// todo 全局样式在每个页面和组件中生效,以支持全局原子类,后续支持样式模块复用后可考虑移除
|
|
183
|
+
Object.assign(result, appClassMap[className])
|
|
184
|
+
} else if (this.__props[className] && isObject(this.__props[className])) {
|
|
183
185
|
// externalClasses必定以对象形式传递下来
|
|
184
|
-
Object.assign(result, this.
|
|
186
|
+
Object.assign(result, this.__props[className])
|
|
185
187
|
}
|
|
186
188
|
})
|
|
187
189
|
}
|
|
@@ -196,7 +198,8 @@ export default function styleHelperMixin () {
|
|
|
196
198
|
display: 'none'
|
|
197
199
|
})
|
|
198
200
|
}
|
|
199
|
-
|
|
201
|
+
|
|
202
|
+
return isEmptyObject(result) ? empty : result
|
|
200
203
|
}
|
|
201
204
|
}
|
|
202
205
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
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, getFocusedNavigation, hasOwn, extend } from '@mpxjs/utils'
|
|
4
4
|
import { mergeLifecycle } from '../convertor/mergeLifecycle'
|
|
5
|
-
import
|
|
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 { Image } from 'react-native'
|
|
9
10
|
import { ref } from '../observer/ref'
|
|
10
11
|
|
|
11
|
-
const appHooksMap = makeMap(mergeLifecycle(
|
|
12
|
+
const appHooksMap = makeMap(mergeLifecycle(LIFECYCLE).app)
|
|
12
13
|
|
|
13
14
|
function getOrientation (window = ReactNative.Dimensions.get('window')) {
|
|
14
15
|
return window.width > window.height ? 'landscape' : 'portrait'
|
|
@@ -30,17 +31,13 @@ function filterOptions (options, appData) {
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
function createAppInstance (appData) {
|
|
33
|
-
|
|
34
|
-
...Mpx.prototype,
|
|
35
|
-
...appData
|
|
36
|
-
}
|
|
37
|
-
return instance
|
|
34
|
+
return extend({}, Mpx.prototype, appData)
|
|
38
35
|
}
|
|
39
36
|
|
|
40
37
|
export default function createApp (option, config = {}) {
|
|
41
38
|
const appData = {}
|
|
42
39
|
|
|
43
|
-
const { NavigationContainer,
|
|
40
|
+
const { NavigationContainer, createStackNavigator, SafeAreaProvider } = global.__navigationHelper
|
|
44
41
|
// app选项目前不需要进行转换
|
|
45
42
|
const { rawOptions, currentInject } = transferOptions(option, 'app', false)
|
|
46
43
|
const defaultOptions = filterOptions(spreadProp(rawOptions, 'methods'), appData)
|
|
@@ -51,16 +48,25 @@ export default function createApp (option, config = {}) {
|
|
|
51
48
|
}
|
|
52
49
|
const pages = currentInject.getPages() || {}
|
|
53
50
|
const firstPage = currentInject.firstPage
|
|
54
|
-
const Stack =
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
const Stack = createStackNavigator()
|
|
52
|
+
const getPageScreens = (initialRouteName, initialParams) => {
|
|
53
|
+
return Object.entries(pages).map(([key, item]) => {
|
|
54
|
+
if (key === initialRouteName) {
|
|
55
|
+
return createElement(Stack.Screen, {
|
|
56
|
+
name: key,
|
|
57
|
+
component: item,
|
|
58
|
+
initialParams
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
return createElement(Stack.Screen, {
|
|
62
|
+
name: key,
|
|
63
|
+
component: item
|
|
64
|
+
})
|
|
60
65
|
})
|
|
61
|
-
}
|
|
66
|
+
}
|
|
62
67
|
global.__mpxOptionsMap = global.__mpxOptionsMap || {}
|
|
63
|
-
const onStateChange = () => {
|
|
68
|
+
const onStateChange = (state) => {
|
|
69
|
+
Mpx.config.rnConfig.onStateChange?.(state)
|
|
64
70
|
if (global.__navigationHelper.lastSuccessCallback) {
|
|
65
71
|
global.__navigationHelper.lastSuccessCallback()
|
|
66
72
|
global.__navigationHelper.lastSuccessCallback = null
|
|
@@ -75,32 +81,48 @@ export default function createApp (option, config = {}) {
|
|
|
75
81
|
}
|
|
76
82
|
}
|
|
77
83
|
|
|
78
|
-
global.
|
|
79
|
-
show: [],
|
|
80
|
-
hide: [],
|
|
81
|
-
error: []
|
|
82
|
-
}
|
|
84
|
+
global.__mpxAppLaunched = false
|
|
83
85
|
|
|
84
86
|
global.__mpxAppFocusedState = ref('show')
|
|
85
|
-
global.__mpxOptionsMap[currentInject.moduleId] = memo(() => {
|
|
87
|
+
global.__mpxOptionsMap[currentInject.moduleId] = memo((props) => {
|
|
86
88
|
const instanceRef = useRef(null)
|
|
87
89
|
if (!instanceRef.current) {
|
|
88
90
|
instanceRef.current = createAppInstance(appData)
|
|
89
91
|
}
|
|
90
92
|
const instance = instanceRef.current
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
const initialRouteRef = useRef({
|
|
94
|
+
initialRouteName: firstPage,
|
|
95
|
+
initialParams: {}
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
if (!global.__mpxAppLaunched) {
|
|
99
|
+
const parsed = Mpx.config.rnConfig.parseAppProps?.(props) || {}
|
|
100
|
+
if (parsed.url) {
|
|
101
|
+
const { path, queryObj } = parseUrlQuery(parsed.url)
|
|
102
|
+
Object.assign(initialRouteRef.current, {
|
|
103
|
+
initialRouteName: path.startsWith('/') ? path.slice(1) : path,
|
|
104
|
+
initialParams: queryObj
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
global.__mpxAppOnLaunch = (navigation) => {
|
|
108
|
+
global.__mpxAppLaunched = true
|
|
109
|
+
const state = navigation.getState()
|
|
110
|
+
Mpx.config.rnConfig.onStateChange?.(state)
|
|
111
|
+
const current = state.routes[state.index]
|
|
112
|
+
global.__mpxEnterOptions = {
|
|
113
|
+
path: current.name,
|
|
114
|
+
query: current.params,
|
|
115
|
+
scene: 0,
|
|
116
|
+
shareTicket: '',
|
|
117
|
+
referrerInfo: {}
|
|
118
|
+
}
|
|
119
|
+
defaultOptions.onLaunch && defaultOptions.onLaunch.call(instance, global.__mpxEnterOptions)
|
|
120
|
+
defaultOptions.onShow && defaultOptions.onShow.call(instance, global.__mpxEnterOptions)
|
|
99
121
|
}
|
|
100
|
-
|
|
101
|
-
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
useEffect(() => {
|
|
102
125
|
if (defaultOptions.onShow) {
|
|
103
|
-
defaultOptions.onShow.call(instance, options)
|
|
104
126
|
global.__mpxAppCbs.show.push(defaultOptions.onShow.bind(instance))
|
|
105
127
|
}
|
|
106
128
|
if (defaultOptions.onHide) {
|
|
@@ -109,18 +131,39 @@ export default function createApp (option, config = {}) {
|
|
|
109
131
|
if (defaultOptions.onError) {
|
|
110
132
|
global.__mpxAppCbs.error.push(defaultOptions.onError.bind(instance))
|
|
111
133
|
}
|
|
134
|
+
if (defaultOptions.onUnhandledRejection) {
|
|
135
|
+
global.__mpxAppCbs.rejection.push(defaultOptions.onUnhandledRejection.bind(instance))
|
|
136
|
+
}
|
|
112
137
|
|
|
113
138
|
const changeSubscription = ReactNative.AppState.addEventListener('change', (currentState) => {
|
|
114
139
|
if (currentState === 'active') {
|
|
140
|
+
let options = global.__mpxEnterOptions
|
|
141
|
+
const navigation = getFocusedNavigation()
|
|
142
|
+
if (navigation) {
|
|
143
|
+
const state = navigation.getState()
|
|
144
|
+
const current = state.routes[state.index]
|
|
145
|
+
options = {
|
|
146
|
+
path: current.name,
|
|
147
|
+
query: current.params,
|
|
148
|
+
scene: 0,
|
|
149
|
+
shareTicket: '',
|
|
150
|
+
referrerInfo: {}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
115
153
|
global.__mpxAppCbs.show.forEach((cb) => {
|
|
116
154
|
cb(options)
|
|
117
155
|
})
|
|
118
|
-
global.
|
|
119
|
-
|
|
156
|
+
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
157
|
+
global.__mpxPageStatusMap[navigation.pageId] = 'show'
|
|
158
|
+
}
|
|
159
|
+
} else if (currentState === 'inactive' || currentState === 'background') {
|
|
120
160
|
global.__mpxAppCbs.hide.forEach((cb) => {
|
|
121
161
|
cb()
|
|
122
162
|
})
|
|
123
|
-
|
|
163
|
+
const navigation = getFocusedNavigation()
|
|
164
|
+
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
165
|
+
global.__mpxPageStatusMap[navigation.pageId] = 'hide'
|
|
166
|
+
}
|
|
124
167
|
}
|
|
125
168
|
})
|
|
126
169
|
|
|
@@ -130,7 +173,10 @@ export default function createApp (option, config = {}) {
|
|
|
130
173
|
const orientation = getOrientation(window)
|
|
131
174
|
if (orientation === lastOrientation) return
|
|
132
175
|
lastOrientation = orientation
|
|
133
|
-
|
|
176
|
+
const navigation = getFocusedNavigation()
|
|
177
|
+
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
178
|
+
global.__mpxPageStatusMap[navigation.pageId] = `resize${count++}`
|
|
179
|
+
}
|
|
134
180
|
})
|
|
135
181
|
return () => {
|
|
136
182
|
changeSubscription && changeSubscription.remove()
|
|
@@ -138,26 +184,41 @@ export default function createApp (option, config = {}) {
|
|
|
138
184
|
}
|
|
139
185
|
}, [])
|
|
140
186
|
|
|
187
|
+
const { initialRouteName, initialParams } = initialRouteRef.current
|
|
188
|
+
const headerBackImageProps = Mpx.config.rnConfig.headerBackImageProps || null
|
|
189
|
+
const navScreenOpts = {
|
|
190
|
+
gestureEnabled: true,
|
|
191
|
+
// 7.x替换headerBackTitleVisible
|
|
192
|
+
// headerBackButtonDisplayMode: 'minimal',
|
|
193
|
+
headerBackTitleVisible: false,
|
|
194
|
+
// 安卓上会出现初始化时闪现导航条的问题
|
|
195
|
+
headerShown: false
|
|
196
|
+
}
|
|
197
|
+
if (headerBackImageProps) {
|
|
198
|
+
navScreenOpts.headerBackImage = () => {
|
|
199
|
+
return createElement(Image, headerBackImageProps)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
141
202
|
return createElement(SafeAreaProvider,
|
|
142
203
|
null,
|
|
143
204
|
createElement(NavigationContainer,
|
|
144
205
|
{
|
|
145
|
-
ref: navigationRef,
|
|
146
206
|
onStateChange,
|
|
147
207
|
onUnhandledAction
|
|
148
208
|
},
|
|
149
209
|
createElement(Stack.Navigator,
|
|
150
210
|
{
|
|
151
|
-
initialRouteName
|
|
211
|
+
initialRouteName,
|
|
212
|
+
screenOptions: navScreenOpts
|
|
152
213
|
},
|
|
153
|
-
...
|
|
214
|
+
...getPageScreens(initialRouteName, initialParams)
|
|
154
215
|
)
|
|
155
216
|
)
|
|
156
217
|
)
|
|
157
218
|
})
|
|
158
219
|
|
|
159
220
|
global.getCurrentPages = function () {
|
|
160
|
-
const navigation =
|
|
221
|
+
const navigation = getFocusedNavigation()
|
|
161
222
|
if (navigation) {
|
|
162
223
|
return navigation.getState().routes.map((route) => {
|
|
163
224
|
return global.__mpxPagesMap[route.key] && global.__mpxPagesMap[route.key][0]
|
|
@@ -165,4 +226,11 @@ export default function createApp (option, config = {}) {
|
|
|
165
226
|
}
|
|
166
227
|
return []
|
|
167
228
|
}
|
|
229
|
+
|
|
230
|
+
global.setCurrentPageStatus = function (status) {
|
|
231
|
+
const navigation = getFocusedNavigation()
|
|
232
|
+
if (navigation && hasOwn(global.__mpxPageStatusMap, navigation.pageId)) {
|
|
233
|
+
global.__mpxPageStatusMap[navigation.pageId] = status
|
|
234
|
+
}
|
|
235
|
+
}
|
|
168
236
|
}
|
|
@@ -3,10 +3,11 @@ import mergeOptions from '../core/mergeOptions'
|
|
|
3
3
|
import builtInKeysMap from './patch/builtInKeysMap'
|
|
4
4
|
import { makeMap, spreadProp, isBrowser } from '@mpxjs/utils'
|
|
5
5
|
import { mergeLifecycle } from '../convertor/mergeLifecycle'
|
|
6
|
-
import
|
|
6
|
+
import { LIFECYCLE } from '../platform/patch/lifecycle/index'
|
|
7
7
|
import Mpx from '../index'
|
|
8
|
+
import { initAppProvides } from './export/inject'
|
|
8
9
|
|
|
9
|
-
const
|
|
10
|
+
const appHooksMap = makeMap(mergeLifecycle(LIFECYCLE).app)
|
|
10
11
|
|
|
11
12
|
function filterOptions (options, appData) {
|
|
12
13
|
const newOptions = {}
|
|
@@ -14,7 +15,7 @@ function filterOptions (options, appData) {
|
|
|
14
15
|
if (builtInKeysMap[key]) {
|
|
15
16
|
return
|
|
16
17
|
}
|
|
17
|
-
if (__mpx_mode__ === 'web' && !
|
|
18
|
+
if (__mpx_mode__ === 'web' && !appHooksMap[key] && key !== 'provide') {
|
|
18
19
|
appData[key] = options[key]
|
|
19
20
|
} else {
|
|
20
21
|
newOptions[key] = options[key]
|
|
@@ -46,11 +47,6 @@ export default function createApp (option, config = {}) {
|
|
|
46
47
|
}
|
|
47
48
|
global.__mpxEnterOptions = options
|
|
48
49
|
this.$options.onLaunch && this.$options.onLaunch.call(this, options)
|
|
49
|
-
global.__mpxAppCbs = global.__mpxAppCbs || {
|
|
50
|
-
show: [],
|
|
51
|
-
hide: [],
|
|
52
|
-
error: []
|
|
53
|
-
}
|
|
54
50
|
if (isBrowser) {
|
|
55
51
|
if (this.$options.onShow) {
|
|
56
52
|
this.$options.onShow.call(this, options)
|
|
@@ -62,6 +58,9 @@ export default function createApp (option, config = {}) {
|
|
|
62
58
|
if (this.$options.onError) {
|
|
63
59
|
global.__mpxAppCbs.error.push(this.$options.onError.bind(this))
|
|
64
60
|
}
|
|
61
|
+
if (this.$options.onUnhandledRejection) {
|
|
62
|
+
global.__mpxAppCbs.rejection.push(this.$options.onUnhandledRejection.bind(this))
|
|
63
|
+
}
|
|
65
64
|
}
|
|
66
65
|
}
|
|
67
66
|
})
|
|
@@ -87,6 +86,7 @@ export default function createApp (option, config = {}) {
|
|
|
87
86
|
return appData
|
|
88
87
|
}
|
|
89
88
|
} else {
|
|
89
|
+
initAppProvides(rawOptions)
|
|
90
90
|
defaultOptions.onAppInit && defaultOptions.onAppInit()
|
|
91
91
|
const ctor = config.customCtor || global.currentCtor || App
|
|
92
92
|
ctor(defaultOptions)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { isBrowser } from '@mpxjs/utils'
|
|
2
|
+
|
|
3
|
+
function extendEvent (e, extendObj = {}) {
|
|
4
|
+
Object.keys(extendObj).forEach((key) => {
|
|
5
|
+
Object.defineProperty(e, key, {
|
|
6
|
+
value: extendObj[key],
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true
|
|
10
|
+
})
|
|
11
|
+
})
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function MpxEvent (layer) {
|
|
15
|
+
this.targetElement = null
|
|
16
|
+
this.touches = []
|
|
17
|
+
this.touchStartX = 0
|
|
18
|
+
this.touchStartY = 0
|
|
19
|
+
this.startTimer = null
|
|
20
|
+
this.needTap = true
|
|
21
|
+
this.isTouchDevice = document && ('ontouchstart' in document.documentElement)
|
|
22
|
+
|
|
23
|
+
this.onTouchStart = (event) => {
|
|
24
|
+
if (event.targetTouches?.length > 1) {
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
this.touches = event.targetTouches
|
|
28
|
+
this.targetElement = event.target
|
|
29
|
+
this.needTap = true
|
|
30
|
+
this.startTimer = null
|
|
31
|
+
this.touchStartX = this.touches[0].pageX
|
|
32
|
+
this.touchStartY = this.touches[0].pageY
|
|
33
|
+
this.startTimer = setTimeout(() => {
|
|
34
|
+
this.needTap = false
|
|
35
|
+
this.sendEvent(this.targetElement, 'longpress', event)
|
|
36
|
+
this.sendEvent(this.targetElement, 'longtap', event)
|
|
37
|
+
}, 350)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.onTouchMove = (event) => {
|
|
41
|
+
const touch = event.changedTouches[0]
|
|
42
|
+
if (Math.abs(touch.pageX - this.touchStartX) > 1 || Math.abs(touch.pageY - this.touchStartY) > 1) {
|
|
43
|
+
this.needTap = false
|
|
44
|
+
this.startTimer && clearTimeout(this.startTimer)
|
|
45
|
+
this.startTimer = null
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
this.onTouchEnd = (event) => {
|
|
50
|
+
if (event.targetTouches?.length > 1) {
|
|
51
|
+
return true
|
|
52
|
+
}
|
|
53
|
+
this.startTimer && clearTimeout(this.startTimer)
|
|
54
|
+
this.startTimer = null
|
|
55
|
+
if (this.needTap) {
|
|
56
|
+
this.sendEvent(this.targetElement, 'tap', event)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.onClick = (event) => {
|
|
61
|
+
this.targetElement = event.target
|
|
62
|
+
this.sendEvent(this.targetElement, 'tap', event)
|
|
63
|
+
}
|
|
64
|
+
this.sendEvent = (targetElement, type, event) => {
|
|
65
|
+
const touchEvent = new CustomEvent(type, {
|
|
66
|
+
bubbles: true,
|
|
67
|
+
cancelable: true
|
|
68
|
+
})
|
|
69
|
+
const changedTouches = event.changedTouches || []
|
|
70
|
+
extendEvent(touchEvent, {
|
|
71
|
+
timeStamp: event.timeStamp,
|
|
72
|
+
changedTouches,
|
|
73
|
+
touches: changedTouches,
|
|
74
|
+
detail: {
|
|
75
|
+
// pc端点击事件可能没有changedTouches,所以直接从 event中取
|
|
76
|
+
x: changedTouches[0]?.pageX || event.pageX || 0,
|
|
77
|
+
y: changedTouches[0]?.pageY || event.pageY || 0
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
targetElement && targetElement.dispatchEvent(touchEvent)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
this.addListener = () => {
|
|
84
|
+
if (this.isTouchDevice) {
|
|
85
|
+
layer.addEventListener('touchstart', this.onTouchStart, true)
|
|
86
|
+
layer.addEventListener('touchmove', this.onTouchMove, true)
|
|
87
|
+
layer.addEventListener('touchend', this.onTouchEnd, true)
|
|
88
|
+
} else {
|
|
89
|
+
layer.addEventListener('click', this.onClick, true)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
this.addListener()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function initEvent () {
|
|
96
|
+
if (isBrowser && !global.__mpxCreatedEvent) {
|
|
97
|
+
global.__mpxCreatedEvent = true
|
|
98
|
+
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
|
99
|
+
// eslint-disable-next-line no-new
|
|
100
|
+
new MpxEvent(document.body)
|
|
101
|
+
} else {
|
|
102
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
103
|
+
// eslint-disable-next-line no-new
|
|
104
|
+
new MpxEvent(document.body)
|
|
105
|
+
}, false)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { createI18n } from '../builtInMixins/i18nMixin'
|
|
2
|
+
|
|
3
|
+
export function init (Mpx) {
|
|
4
|
+
global.__mpx = Mpx
|
|
5
|
+
global.__mpxAppCbs = global.__mpxAppCbs || {
|
|
6
|
+
show: [],
|
|
7
|
+
hide: [],
|
|
8
|
+
error: [],
|
|
9
|
+
rejection: []
|
|
10
|
+
}
|
|
11
|
+
if (global.i18n) {
|
|
12
|
+
Mpx.i18n = createI18n(global.i18n)
|
|
13
|
+
}
|
|
14
|
+
initGlobalErrorHandling()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function initGlobalErrorHandling () {
|
|
18
|
+
if (global.ErrorUtils) {
|
|
19
|
+
const defaultHandler = global.ErrorUtils.getGlobalHandler()
|
|
20
|
+
global.ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
21
|
+
if (global.__mpxAppCbs && global.__mpxAppCbs.error && global.__mpxAppCbs.error.length) {
|
|
22
|
+
global.__mpxAppCbs.error.forEach((cb) => {
|
|
23
|
+
cb(error)
|
|
24
|
+
})
|
|
25
|
+
} else if (defaultHandler) {
|
|
26
|
+
defaultHandler(error, isFatal)
|
|
27
|
+
} else {
|
|
28
|
+
console.error(`${error.name}: ${error.message}\n`)
|
|
29
|
+
}
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const rejectionTrackingOptions = {
|
|
34
|
+
allRejections: true,
|
|
35
|
+
onUnhandled (id, error) {
|
|
36
|
+
if (global.__mpxAppCbs && global.__mpxAppCbs.rejection && global.__mpxAppCbs.rejection.length) {
|
|
37
|
+
global.__mpxAppCbs.rejection.forEach((cb) => {
|
|
38
|
+
cb(error, id)
|
|
39
|
+
})
|
|
40
|
+
} else {
|
|
41
|
+
console.warn(`UNHANDLED PROMISE REJECTION (id: ${id}): ${error}\n`)
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (global?.HermesInternal?.hasPromise?.()) {
|
|
47
|
+
global.HermesInternal?.enablePromiseRejectionTracker?.(rejectionTrackingOptions)
|
|
48
|
+
} else {
|
|
49
|
+
require('promise/setimmediate/rejection-tracking').enable(rejectionTrackingOptions)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import Vue from 'vue'
|
|
2
|
+
import install from './vuePlugin'
|
|
3
|
+
import { isBrowser, error, warn } from '@mpxjs/utils'
|
|
4
|
+
import { initEvent } from './event'
|
|
5
|
+
|
|
6
|
+
export function init (Mpx) {
|
|
7
|
+
global.__mpx = Mpx
|
|
8
|
+
global.__mpxAppCbs = global.__mpxAppCbs || {
|
|
9
|
+
show: [],
|
|
10
|
+
hide: [],
|
|
11
|
+
error: [],
|
|
12
|
+
rejection: []
|
|
13
|
+
}
|
|
14
|
+
Mpx.__vue = Vue
|
|
15
|
+
Vue.use(install)
|
|
16
|
+
initEvent()
|
|
17
|
+
initGlobalErrorHandling()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function initGlobalErrorHandling () {
|
|
21
|
+
Vue.config.errorHandler = (e, vm, info) => {
|
|
22
|
+
error(`Unhandled error occurs${info ? ` during execution of [${info}]` : ''}!`, vm?.__mpxProxy?.options.mpxFileResource, e)
|
|
23
|
+
}
|
|
24
|
+
Vue.config.warnHandler = (msg, vm, trace) => {
|
|
25
|
+
warn(msg, vm?.__mpxProxy?.options.mpxFileResource, trace)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (isBrowser) {
|
|
29
|
+
window.addEventListener('error', (event) => {
|
|
30
|
+
if (global.__mpxAppCbs && global.__mpxAppCbs.error && global.__mpxAppCbs.error.length) {
|
|
31
|
+
global.__mpxAppCbs.error.forEach((cb) => {
|
|
32
|
+
cb(event.error)
|
|
33
|
+
})
|
|
34
|
+
} else {
|
|
35
|
+
console.error(`${event.type}: ${event.message}\n`)
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
window.addEventListener('unhandledrejection', (event) => {
|
|
39
|
+
if (global.__mpxAppCbs && global.__mpxAppCbs.rejection && global.__mpxAppCbs.rejection.length) {
|
|
40
|
+
global.__mpxAppCbs.rejection.forEach((cb) => {
|
|
41
|
+
cb(event.reason, event.promise)
|
|
42
|
+
})
|
|
43
|
+
} else {
|
|
44
|
+
console.warn(`UNHANDLED PROMISE REJECTION: ${event.reason}\n`)
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { walkChildren, parseSelector, error, hasOwn, collectDataset } from '@mpxjs/utils'
|
|
2
2
|
import { createSelectorQuery, createIntersectionObserver } from '@mpxjs/api-proxy'
|
|
3
3
|
import { EffectScope } from 'vue'
|
|
4
|
-
import { PausedState } from '
|
|
4
|
+
import { PausedState } from '../../helper/const'
|
|
5
5
|
|
|
6
6
|
const hackEffectScope = () => {
|
|
7
7
|
EffectScope.prototype.pause = function () {
|