@mpxjs/core 2.9.39 → 2.9.41

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.
Files changed (34) hide show
  1. package/package.json +37 -3
  2. package/src/convertor/convertor.js +4 -1
  3. package/src/convertor/getConvertMode.js +3 -1
  4. package/src/convertor/wxToReact.js +31 -0
  5. package/src/core/proxy.js +27 -5
  6. package/src/core/transferOptions.js +9 -1
  7. package/src/{vuePlugin.js → external/vuePlugin.js} +1 -1
  8. package/src/index.js +6 -2
  9. package/src/platform/builtInMixins/directiveHelperMixin.android.js +2 -0
  10. package/src/platform/builtInMixins/directiveHelperMixin.ios.js +15 -0
  11. package/src/platform/builtInMixins/directiveHelperMixin.js +3 -0
  12. package/src/platform/builtInMixins/index.js +12 -2
  13. package/src/platform/builtInMixins/proxyEventMixin.android.js +2 -0
  14. package/src/platform/builtInMixins/proxyEventMixin.ios.js +49 -0
  15. package/src/platform/builtInMixins/proxyEventMixin.js +0 -11
  16. package/src/platform/builtInMixins/refsMixin.android.js +2 -0
  17. package/src/platform/builtInMixins/refsMixin.ios.js +311 -0
  18. package/src/platform/builtInMixins/styleHelperMixin.android.js +2 -0
  19. package/src/platform/builtInMixins/styleHelperMixin.ios.js +141 -0
  20. package/src/platform/builtInMixins/styleHelperMixin.js +3 -0
  21. package/src/platform/createApp.android.js +2 -0
  22. package/src/platform/createApp.ios.js +104 -0
  23. package/src/platform/createApp.js +3 -5
  24. package/src/platform/export/api.web.js +1 -1
  25. package/src/platform/patch/ali/getDefaultOptions.js +4 -4
  26. package/src/platform/patch/index.js +9 -6
  27. package/src/platform/patch/react/getDefaultOptions.android.js +1 -0
  28. package/src/platform/patch/react/getDefaultOptions.ios.js +280 -0
  29. package/src/platform/patch/react/getDefaultOptions.js +1 -0
  30. package/src/platform/patch/swan/getDefaultOptions.js +1 -1
  31. package/src/platform/patch/web/getDefaultOptions.js +13 -3
  32. package/src/platform/patch/wx/getDefaultOptions.js +1 -1
  33. /package/src/{vue.js → external/vue.js} +0 -0
  34. /package/src/{vue.web.js → external/vue.web.js} +0 -0
@@ -0,0 +1,311 @@
1
+ import { BEFORECREATE } from '../../core/innerLifecycle'
2
+ import { noop, isBoolean, dash2hump, warn, collectDataset, hump2dash } from '@mpxjs/utils'
3
+ import { StyleSheet } from 'react-native'
4
+
5
+ const _createSelectorQuery = (runCb) => {
6
+ return {
7
+ exec: (cb = noop) => {
8
+ runCb().then(res => {
9
+ cb(res)
10
+ })
11
+ },
12
+ in: () => {
13
+ warn('please use wx:ref to get NodesRef')
14
+ },
15
+ select: () => {
16
+ warn('please use wx:ref to get NodesRef')
17
+ },
18
+ selectAll: () => {
19
+ warn('please use wx:ref to get NodesRef')
20
+ },
21
+ selectViewport: () => { // 有点难实现,dimension 目前没有暴露相关 api
22
+ warn('please use wx:ref')
23
+ }
24
+ }
25
+ }
26
+
27
+ const flushRefFns = (nodeInstances, fns) => {
28
+ const mountedNodeInstance = nodeInstances
29
+ .map(instance => instance.getNodeInstance())
30
+ .filter(({ nodeRef }) => nodeRef.current) // 如果有 nodeRef,表明目前组件处于挂载中
31
+ if (mountedNodeInstance.length) {
32
+ return Promise.all(mountedNodeInstance.map(instance => flushFns(instance, fns)))
33
+ } else {
34
+ return Promise.resolve(null)
35
+ }
36
+ }
37
+
38
+ const flushFns = (nodeInstance, fns) => {
39
+ return Promise.all(fns.map(fn => fn(nodeInstance))).then((res) => {
40
+ return res.reduce((preVal, curVal) => {
41
+ return Object.assign(preVal, curVal)
42
+ }, {})
43
+ })
44
+ }
45
+
46
+ const wrapFn = (fn) => {
47
+ return (nodeRef) => {
48
+ return new Promise((resolve) => {
49
+ fn(nodeRef, resolve)
50
+ })
51
+ }
52
+ }
53
+
54
+ const getMeasureProps = (measureProps = []) => {
55
+ return wrapFn((nodeInstance, resolve) => {
56
+ const nodeRef = nodeInstance.nodeRef.current
57
+ setTimeout(() => {
58
+ nodeRef.measure(function (x, y, width, height, pageX, pageY) {
59
+ const rectAndSize = {
60
+ width,
61
+ height,
62
+ left: pageX,
63
+ top: pageY,
64
+ right: pageX + width,
65
+ bottom: pageY + height
66
+ }
67
+ const result = measureProps.reduce((preVal, key) => {
68
+ return Object.assign(preVal, { [key]: rectAndSize[key] || 0 })
69
+ }, {})
70
+ resolve(result)
71
+ })
72
+ }, 30) // 延迟,等待组件在rn视图上真正渲染出来
73
+ })
74
+ }
75
+
76
+ const getDataset = (props) => {
77
+ return wrapFn((nodeRef, resolve) => {
78
+ props = nodeRef.props.current
79
+ resolve({
80
+ dataset: collectDataset(props)
81
+ })
82
+ })
83
+ }
84
+
85
+ const getPlainProps = (config) => {
86
+ return wrapFn((nodeRef, resolve) => {
87
+ const res = {}
88
+ const props = nodeRef.props.current
89
+ config.forEach((key) => {
90
+ // props 属性默认不转驼峰,用户写什么格式不会变化,取值做兼容
91
+ res[key] = props[key] || props[hump2dash(key)] || ''
92
+ })
93
+ resolve(res)
94
+ })
95
+ }
96
+
97
+ const getComputedStyle = (config = []) => {
98
+ return wrapFn((nodeRef, resolve) => {
99
+ config = new Set(config)
100
+ const res = {}
101
+ const styles = nodeRef.props.current.style || []
102
+ const defaultStyle = nodeRef.instance.defaultStyle || {}
103
+ const computedStyle = StyleSheet.flatten([defaultStyle, ...styles])
104
+ config.forEach((key) => {
105
+ const humpKey = dash2hump(key)
106
+ // 取 style 的 key 是根据传入的 key 来设置,传什么设置什么 key,只不过取值需要做兼容
107
+ res[key] = computedStyle[key] || computedStyle[humpKey] || ''
108
+ })
109
+
110
+ resolve(res)
111
+ })
112
+ }
113
+
114
+ const getInstanceConfig = (config) => {
115
+ return wrapFn((nodeRef, resolve) => {
116
+ const instance = nodeRef.instance
117
+ resolve({ [config]: instance[config] || {} })
118
+ })
119
+ }
120
+
121
+ const defaultScrollOffset = {
122
+ scrollLeft: 0,
123
+ scrollTop: 0,
124
+ scrollHeight: 0,
125
+ scrollWidth: 0
126
+ }
127
+
128
+ const getScrollOffset = () => {
129
+ return wrapFn((nodeRef, resolve) => {
130
+ const instance = nodeRef.instance
131
+ resolve((instance.scrollOffset && instance.scrollOffset.current) || defaultScrollOffset)
132
+ })
133
+ }
134
+
135
+ // const getScrollOffsetFallback = (cb) => {
136
+ // const res = {
137
+ // scrollLeft: 0,
138
+ // scrollTop: 0,
139
+ // scrollHeight: 0,
140
+ // scrollWidth: 0
141
+ // }
142
+ // cb(res)
143
+ // }
144
+
145
+ const RECT = ['left', 'top', 'right', 'bottom']
146
+ const SIZE = ['width', 'height']
147
+
148
+ function _createNodesRef (nodeRefs = []) {
149
+ const fields = (config, cb = noop) => {
150
+ const plainProps = []
151
+ const measureProps = []
152
+ const computedStyle = []
153
+ const fns = []
154
+
155
+ for (const key in config) {
156
+ const value = config[key]
157
+ if (Array.isArray(value) && value.length) {
158
+ if (key === 'properties') {
159
+ // wx 最终输出的 properties 字段都会转化为驼峰,所以在这里提前处理为最终的字段格式
160
+ plainProps.push(...value.map(v => dash2hump(v)))
161
+ } else if (key === 'computedStyle') {
162
+ const _computedStyle = config.computedStyle
163
+ for (let i = _computedStyle.length - 1; i >= 0; i--) {
164
+ const style = _computedStyle[i]
165
+ if (RECT.includes(style) || SIZE.includes(style)) {
166
+ measureProps.push(style)
167
+ _computedStyle.splice(i, 1)
168
+ }
169
+ }
170
+ if (_computedStyle.length) {
171
+ computedStyle.push(..._computedStyle)
172
+ }
173
+ }
174
+ } else if (isBoolean(value) && value) {
175
+ switch (key) {
176
+ case 'rect':
177
+ measureProps.push(...RECT)
178
+ break
179
+ case 'size':
180
+ measureProps.push(...SIZE)
181
+ break
182
+ case 'scrollOffset':
183
+ fns.push(getScrollOffset())
184
+ break
185
+ case 'dataset':
186
+ fns.push(getDataset())
187
+ break
188
+ case 'node':
189
+ case 'context':
190
+ case 'ref':
191
+ fns.push(getInstanceConfig(key))
192
+ break
193
+ default:
194
+ plainProps.push(key)
195
+ break
196
+ }
197
+ }
198
+ }
199
+
200
+ if (plainProps.length) {
201
+ fns.push(getPlainProps(plainProps))
202
+ }
203
+ if (measureProps.length) {
204
+ const nodeInstance = nodeRefs[0] && nodeRefs[0].getNodeInstance()
205
+ const hasMeasureFn = nodeInstance && nodeInstance.nodeRef.current && nodeInstance.nodeRef.current.measure
206
+ if (hasMeasureFn) {
207
+ fns.push(getMeasureProps(measureProps))
208
+ } else {
209
+ computedStyle.push(...measureProps)
210
+ }
211
+ }
212
+ if (computedStyle.length) {
213
+ fns.push(getComputedStyle(computedStyle))
214
+ }
215
+
216
+ const runCb = () => {
217
+ return flushRefFns(nodeRefs, fns).then((result) => {
218
+ // wx的数据格式:对于具体方法接受到的回调传参,如果获取的 nodeRef 只有一个,那么只需要返回一条数据而不是数组,但是 exec 里面统一都是数组
219
+ cb(result && result.length === 1 ? result[0] : result)
220
+ return result
221
+ })
222
+ }
223
+
224
+ return _createSelectorQuery(runCb)
225
+ }
226
+
227
+ const boundingClientRect = (cb = noop) => {
228
+ const config = {
229
+ id: true,
230
+ dataset: true,
231
+ rect: true,
232
+ size: true
233
+ }
234
+ return fields(config, cb)
235
+ }
236
+
237
+ const context = (cb = noop) => {
238
+ const config = {
239
+ context: true
240
+ }
241
+ return fields(config, cb)
242
+ }
243
+
244
+ const node = (cb = noop) => {
245
+ const config = {
246
+ node: true
247
+ }
248
+ return fields(config, cb)
249
+ }
250
+
251
+ const ref = (cb = noop) => {
252
+ const config = {
253
+ ref: true
254
+ }
255
+ return fields(config, cb)
256
+ }
257
+
258
+ const scrollOffset = (cb = noop) => {
259
+ const config = {
260
+ id: true,
261
+ dataset: true,
262
+ scrollOffset: true
263
+ }
264
+ return fields(config, cb)
265
+ }
266
+
267
+ return {
268
+ fields,
269
+ boundingClientRect,
270
+ context,
271
+ node,
272
+ ref,
273
+ scrollOffset
274
+ }
275
+ }
276
+
277
+ export default function getRefsMixin () {
278
+ return {
279
+ [BEFORECREATE] () {
280
+ this.__refs = {}
281
+ this.$refs = {}
282
+ this.__getRefs()
283
+ },
284
+ methods: {
285
+ __getRefs () {
286
+ const refs = this.__getRefsData() || []
287
+ const target = this
288
+ refs.forEach(({ key, type, all }) => {
289
+ Object.defineProperty(this.$refs, key, {
290
+ enumerable: true,
291
+ configurable: true,
292
+ get () {
293
+ const refs = target.__refs[key] || []
294
+ if (type === 'component') {
295
+ return all ? refs : refs[0]
296
+ } else {
297
+ return _createNodesRef(refs)
298
+ }
299
+ }
300
+ })
301
+ })
302
+ },
303
+ __getRefVal (key) {
304
+ if (!this.__refs[key]) {
305
+ this.__refs[key] = []
306
+ }
307
+ return (instance) => instance && this.__refs[key].push(instance)
308
+ }
309
+ }
310
+ }
311
+ }
@@ -0,0 +1,2 @@
1
+ import styleHelperMixin from './styleHelperMixin.ios'
2
+ export default styleHelperMixin
@@ -0,0 +1,141 @@
1
+ import { isObject, isArray, dash2hump, isFunction, isEmptyObject } from '@mpxjs/utils'
2
+ import { Dimensions } from 'react-native'
3
+
4
+ function concat (a, b) {
5
+ return a ? b ? (a + ' ' + b) : a : (b || '')
6
+ }
7
+
8
+ function stringifyArray (value) {
9
+ let res = ''
10
+ let classString
11
+ for (let i = 0; i < value.length; i++) {
12
+ if ((classString = stringifyDynamicClass(value[i]))) {
13
+ if (res) res += ' '
14
+ res += classString
15
+ }
16
+ }
17
+ return res
18
+ }
19
+
20
+ function stringifyObject (value) {
21
+ let res = ''
22
+ const keys = Object.keys(value)
23
+ for (let i = 0; i < keys.length; i++) {
24
+ const key = keys[i]
25
+ if (value[key]) {
26
+ if (res) res += ' '
27
+ res += key
28
+ }
29
+ }
30
+ return res
31
+ }
32
+
33
+ function stringifyDynamicClass (value) {
34
+ if (isArray(value)) {
35
+ value = stringifyArray(value)
36
+ } else if (isObject(value)) {
37
+ value = stringifyObject(value)
38
+ }
39
+ return value
40
+ }
41
+
42
+ const listDelimiter = /;(?![^(]*[)])/g
43
+ const propertyDelimiter = /:(.+)/
44
+ const rpxRegExp = /^\s*(\d+(\.\d+)?)rpx\s*$/
45
+ const pxRegExp = /^\s*(\d+(\.\d+)?)(px)?\s*$/
46
+
47
+ function parseStyleText (cssText) {
48
+ const res = {}
49
+ const arr = cssText.split(listDelimiter)
50
+ for (let i = 0; i < arr.length; i++) {
51
+ const item = arr[i]
52
+ if (item) {
53
+ const tmp = item.split(propertyDelimiter)
54
+ if (tmp.length > 1) {
55
+ const k = dash2hump(tmp[0].trim())
56
+ res[k] = tmp[1].trim()
57
+ }
58
+ }
59
+ }
60
+ return res
61
+ }
62
+
63
+ function normalizeDynamicStyle (value) {
64
+ if (!value) return {}
65
+ if (isArray(value)) {
66
+ return mergeObjectArray(value)
67
+ }
68
+ if (typeof value === 'string') {
69
+ return parseStyleText(value)
70
+ }
71
+ return value
72
+ }
73
+
74
+ function mergeObjectArray (arr) {
75
+ const res = {}
76
+ for (let i = 0; i < arr.length; i++) {
77
+ Object.assign(res, arr[i])
78
+ }
79
+ return res
80
+ }
81
+
82
+ function transformStyleObj (context, styleObj) {
83
+ const keys = Object.keys(styleObj)
84
+ const transformed = {}
85
+ keys.forEach((prop) => {
86
+ // todo 检测不支持的prop
87
+ let value = styleObj[prop]
88
+ let matched
89
+ if ((matched = pxRegExp.exec(value))) {
90
+ value = +matched[1]
91
+ } else if ((matched = rpxRegExp.exec(value))) {
92
+ value = context.__rpx(+matched[1])
93
+ }
94
+ // todo 检测不支持的value
95
+ transformed[prop] = value
96
+ })
97
+ return transformed
98
+ }
99
+
100
+ export default function styleHelperMixin (type) {
101
+ return {
102
+ methods: {
103
+ __rpx (value) {
104
+ const { width } = Dimensions.get('screen')
105
+ // rn 单位 dp = 1(css)px = 1 物理像素 * pixelRatio(像素比)
106
+ // px = rpx * (750 / 屏幕宽度)
107
+ return value * width / 750
108
+ },
109
+ __getStyle (staticClass, dynamicClass, staticStyle, dynamicStyle, show) {
110
+ const result = []
111
+ const classMap = {}
112
+ if (type === 'page' && isFunction(global.__getAppClassMap)) {
113
+ Object.assign(classMap, global.__getAppClassMap.call(this))
114
+ }
115
+ if (isFunction(this.__getClassMap)) {
116
+ Object.assign(classMap, this.__getClassMap())
117
+ }
118
+ if ((staticClass || dynamicClass) && !isEmptyObject(classMap)) {
119
+ const classString = concat(staticClass, stringifyDynamicClass(dynamicClass))
120
+ classString.split(' ').forEach((className) => {
121
+ if (classMap[className]) {
122
+ result.push(classMap[className])
123
+ }
124
+ })
125
+ }
126
+
127
+ if (staticStyle || dynamicStyle) {
128
+ const styleObj = Object.assign(parseStyleText(staticStyle), normalizeDynamicStyle(dynamicStyle))
129
+ result.push(transformStyleObj(this, styleObj))
130
+ }
131
+
132
+ if (show === false) {
133
+ result.push({
134
+ display: 'none'
135
+ })
136
+ }
137
+ return result
138
+ }
139
+ }
140
+ }
141
+ }
@@ -0,0 +1,3 @@
1
+ export default function styleHelperMixin () {
2
+ return {}
3
+ }
@@ -0,0 +1,2 @@
1
+ import createApp from './createApp.ios'
2
+ export default createApp
@@ -0,0 +1,104 @@
1
+ import transferOptions from '../core/transferOptions'
2
+ import builtInKeysMap from './patch/builtInKeysMap'
3
+ import { makeMap, spreadProp } from '@mpxjs/utils'
4
+ import { mergeLifecycle } from '../convertor/mergeLifecycle'
5
+ import * as wxLifecycle from '../platform/patch/wx/lifecycle'
6
+ import Mpx from '../index'
7
+ import { createElement, memo, useRef, useEffect } from 'react'
8
+
9
+ const appHooksMap = makeMap(mergeLifecycle(wxLifecycle.LIFECYCLE).app)
10
+
11
+ function filterOptions (options, appData) {
12
+ const newOptions = {}
13
+ Object.keys(options).forEach(key => {
14
+ if (builtInKeysMap[key]) {
15
+ return
16
+ }
17
+ if (!appHooksMap[key]) {
18
+ appData[key] = options[key]
19
+ } else {
20
+ newOptions[key] = options[key]
21
+ }
22
+ })
23
+ return newOptions
24
+ }
25
+
26
+ function createAppInstance (appData) {
27
+ const instance = {
28
+ ...Mpx.prototype,
29
+ ...appData
30
+ }
31
+ return instance
32
+ }
33
+
34
+ export default function createApp (option, config = {}) {
35
+ const appData = {}
36
+
37
+ const { NavigationContainer, createNavigationContainerRef, createNativeStackNavigator } = global.__navigationHelper
38
+ // app选项目前不需要进行转换
39
+ const { rawOptions, currentInject } = transferOptions(option, 'app', false)
40
+ const defaultOptions = filterOptions(spreadProp(rawOptions, 'methods'), appData)
41
+ defaultOptions.onAppInit && defaultOptions.onAppInit()
42
+ const pages = currentInject.getPages() || {}
43
+ const firstPage = currentInject.firstPage
44
+ const Stack = createNativeStackNavigator()
45
+ const navigationRef = createNavigationContainerRef()
46
+ const pageScreens = Object.entries(pages).map(([key, item]) => {
47
+ return createElement(Stack.Screen, {
48
+ name: key,
49
+ component: item
50
+ })
51
+ })
52
+ global.__navigationRef = navigationRef
53
+ global.__mpxOptionsMap = global.__mpxOptionsMap || {}
54
+ const onStateChange = () => {
55
+ if (global.__navigationHelper.lastSuccessCallback) {
56
+ global.__navigationHelper.lastSuccessCallback()
57
+ global.__navigationHelper.lastSuccessCallback = null
58
+ }
59
+ }
60
+ const onUnhandledAction = (action) => {
61
+ const payload = action.payload
62
+ const message = `The action '${action.type}'${payload ? ` with payload ${JSON.stringify(action.payload)}` : ''} was not handled by any navigator.`
63
+ if (global.__navigationHelper.lastFailCallback) {
64
+ global.__navigationHelper.lastFailCallback(message)
65
+ global.__navigationHelper.lastFailCallback = null
66
+ }
67
+ }
68
+ global.__mpxOptionsMap[currentInject.moduleId] = memo(() => {
69
+ const instanceRef = useRef(null)
70
+ if (!instanceRef.current) {
71
+ instanceRef.current = createAppInstance(appData)
72
+ }
73
+ const instance = instanceRef.current
74
+ useEffect(() => {
75
+ const current = navigationRef.isReady() ? navigationRef.getCurrentRoute() : {}
76
+ const options = {
77
+ path: current.name,
78
+ query: current.params,
79
+ scene: 0,
80
+ shareTicket: '',
81
+ referrerInfo: {}
82
+ }
83
+ global.__mpxEnterOptions = options
84
+ // todo relaunch时会重复执行,需check
85
+ defaultOptions.onLaunch && defaultOptions.onLaunch.call(instance, options)
86
+ }, [])
87
+ return createElement(NavigationContainer,
88
+ {
89
+ ref: navigationRef,
90
+ onStateChange,
91
+ onUnhandledAction
92
+ },
93
+ createElement(Stack.Navigator,
94
+ {
95
+ initialRouteName: firstPage
96
+ },
97
+ ...pageScreens
98
+ )
99
+ )
100
+ })
101
+ global.getApp = function () {
102
+ return appData
103
+ }
104
+ }
@@ -66,9 +66,6 @@ export default function createApp (option, config = {}) {
66
66
  }
67
67
  })
68
68
  } else {
69
- if (option.onAppInit) {
70
- option.onAppInit()
71
- }
72
69
  builtInMixins.push({
73
70
  onLaunch () {
74
71
  Object.assign(this, Mpx.prototype)
@@ -76,13 +73,13 @@ export default function createApp (option, config = {}) {
76
73
  })
77
74
  }
78
75
  // app选项目前不需要进行转换
79
- const { rawOptions } = transferOptions(option, 'app', false)
76
+ const { rawOptions, currentInject } = transferOptions(option, 'app', false)
80
77
  rawOptions.mixins = builtInMixins
81
78
  const defaultOptions = filterOptions(spreadProp(mergeOptions(rawOptions, 'app', false), 'methods'), appData)
82
79
 
83
80
  if (__mpx_mode__ === 'web') {
84
81
  global.__mpxOptionsMap = global.__mpxOptionsMap || {}
85
- global.__mpxOptionsMap[global.currentModuleId] = defaultOptions
82
+ global.__mpxOptionsMap[currentInject.moduleId] = defaultOptions
86
83
  global.getApp = function () {
87
84
  if (!isBrowser) {
88
85
  console.error('[Mpx runtime error]: Dangerous API! global.getApp method is running in non browser environments')
@@ -90,6 +87,7 @@ export default function createApp (option, config = {}) {
90
87
  return appData
91
88
  }
92
89
  } else {
90
+ defaultOptions.onAppInit && defaultOptions.onAppInit()
93
91
  const ctor = config.customCtor || global.currentCtor || App
94
92
  ctor(defaultOptions)
95
93
  }
@@ -1,4 +1,4 @@
1
- import Vue from '../../vue'
1
+ import Vue from 'vue'
2
2
  import { injectMixins } from '../../core/injectMixins'
3
3
 
4
4
  const vm = new Vue()
@@ -122,14 +122,14 @@ function initProxy (context, rawOptions, currentInject) {
122
122
  }
123
123
  }
124
124
 
125
- export function getDefaultOptions (type, { rawOptions = {}, currentInject }) {
125
+ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
126
126
  const hookNames = type === 'component' ? ['onInit', 'didMount', 'didUnmount'] : ['onLoad', 'onReady', 'onUnload']
127
127
  const rootMixins = [{
128
128
  [hookNames[0]] () {
129
129
  if (rawOptions.__nativeRender__ && this.props) {
130
130
  const validProps = Object.assign({}, rawOptions.props, rawOptions.properties)
131
131
  Object.keys(this.props).forEach((key) => {
132
- if (hasOwn(validProps, key) && typeof this.props[key] !== 'function') {
132
+ if (hasOwn(validProps, key) && !isFunction(this.props[key])) {
133
133
  this.data[key] = this.props[key]
134
134
  }
135
135
  })
@@ -143,7 +143,7 @@ export function getDefaultOptions (type, { rawOptions = {}, currentInject }) {
143
143
  const newData = {}
144
144
  // 微信原生转换支付宝时,每次props更新将其设置进data模拟微信表现
145
145
  Object.keys(nextProps).forEach((key) => {
146
- if (hasOwn(validProps, key) && typeof nextProps[key] !== 'function') {
146
+ if (hasOwn(validProps, key) && !isFunction(nextProps[key])) {
147
147
  const { diff, clone } = diffAndCloneA(nextProps[key], this.props[key])
148
148
  if (diff) newData[key] = clone
149
149
  }
@@ -153,7 +153,7 @@ export function getDefaultOptions (type, { rawOptions = {}, currentInject }) {
153
153
  // 由于支付宝中props透传父级setData的值,此处发生变化的属性实例一定不同,只需浅比较即可确定发生变化的属性
154
154
  // 支付宝appx2.0版本后props传递发生变化,此处获取到的nextProps和this.props以及父组件setData的数据引用都不一致,进行了两次深克隆,此处this.props和nextProps的比对需要用deep diff
155
155
  Object.keys(nextProps).forEach(key => {
156
- if (hasOwn(validProps, key) && typeof nextProps[key] !== 'function') {
156
+ if (hasOwn(validProps, key) && !isFunction(nextProps[key])) {
157
157
  const { diff, clone } = diffAndCloneA(nextProps[key], this.props[key])
158
158
  // 由于支付宝中透传父级setData的值,此处进行深clone后赋值避免父级存储的miniRenderData部分数据在此处被响应化,在子组件对props赋值时触发父组件的render
159
159
  if (diff) this[key] = clone
@@ -4,14 +4,15 @@ import { getDefaultOptions as getWxDefaultOptions } from './wx/getDefaultOptions
4
4
  import { getDefaultOptions as getAliDefaultOptions } from './ali/getDefaultOptions'
5
5
  import { getDefaultOptions as getSwanDefaultOptions } from './swan/getDefaultOptions'
6
6
  import { getDefaultOptions as getWebDefaultOptions } from './web/getDefaultOptions'
7
- import { error } from '@mpxjs/utils'
7
+ import { getDefaultOptions as getReactDefaultOptions } from './react/getDefaultOptions'
8
+ import { error, isReact } from '@mpxjs/utils'
8
9
 
9
10
  export default function createFactory (type) {
10
11
  return (options = {}, { isNative, customCtor, customCtorType } = {}) => {
11
12
  options.__nativeRender__ = !!isNative
12
13
  options.__type__ = type
13
14
  let ctor
14
- if (__mpx_mode__ !== 'web') {
15
+ if (__mpx_mode__ !== 'web' && !isReact) {
15
16
  if (customCtor) {
16
17
  ctor = customCtor
17
18
  customCtorType = customCtorType || type
@@ -39,7 +40,9 @@ export default function createFactory (type) {
39
40
  }
40
41
 
41
42
  let getDefaultOptions
42
- if (__mpx_mode__ === 'web') {
43
+ if (isReact) {
44
+ getDefaultOptions = getReactDefaultOptions
45
+ } else if (__mpx_mode__ === 'web') {
43
46
  getDefaultOptions = getWebDefaultOptions
44
47
  } else if (__mpx_mode__ === 'ali') {
45
48
  getDefaultOptions = getAliDefaultOptions
@@ -56,10 +59,10 @@ export default function createFactory (type) {
56
59
  // 注入内建的mixins, 内建mixin是按原始平台编写的,所以合并规则和rootMixins保持一致
57
60
  // 将合并后的用户定义的rawOptions传入获取当前应该注入的内建mixins
58
61
  rawOptions.mixins = getBuiltInMixins(rawOptions, type)
59
- const defaultOptions = getDefaultOptions(type, { rawOptions, currentInject })
60
- if (__mpx_mode__ === 'web') {
62
+ const defaultOptions = getDefaultOptions({ type, rawOptions, currentInject })
63
+ if (__mpx_mode__ === 'web' || isReact) {
61
64
  global.__mpxOptionsMap = global.__mpxOptionsMap || {}
62
- global.__mpxOptionsMap[global.currentModuleId] = defaultOptions
65
+ global.__mpxOptionsMap[currentInject.moduleId] = defaultOptions
63
66
  } else if (ctor) {
64
67
  return ctor(defaultOptions)
65
68
  }
@@ -0,0 +1 @@
1
+ export { getDefaultOptions } from './getDefaultOptions.ios'