@mpxjs/core 2.9.59 → 2.9.64

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.
@@ -8,4 +8,4 @@ declare let __mpx_env__: string
8
8
  declare module '*?resolve' {
9
9
  const resourcePath: string
10
10
  export default resourcePath
11
- }
11
+ }
package/@types/index.d.ts CHANGED
@@ -7,10 +7,8 @@
7
7
  /// <reference path="./global.d.ts" />
8
8
  /// <reference path="./node.d.ts" />
9
9
 
10
- // @ts-ignore
11
10
  import { GetComputedType } from '@mpxjs/store'
12
11
 
13
- // @ts-ignore
14
12
  export * from '@mpxjs/store'
15
13
 
16
14
  // utils
@@ -34,17 +32,17 @@ type Data = object | (() => object)
34
32
  export type PropType<T> = {
35
33
  __type: T
36
34
  } & (
37
- T extends String
35
+ T extends string
38
36
  ? StringConstructor
39
37
  : T extends number
40
- ? NumberConstructor
41
- : T extends boolean
42
- ? BooleanConstructor
43
- : T extends any[]
44
- ? ArrayConstructor
45
- : T extends object
46
- ? ObjectConstructor
47
- : never
38
+ ? NumberConstructor
39
+ : T extends boolean
40
+ ? BooleanConstructor
41
+ : T extends any[]
42
+ ? ArrayConstructor
43
+ : T extends object
44
+ ? ObjectConstructor
45
+ : never
48
46
  )
49
47
 
50
48
  type FullPropType<T> = {
@@ -85,10 +83,10 @@ type GetDataType<T> = T extends () => any ? ReturnType<T> : T
85
83
 
86
84
  type GetPropsType<T extends Properties> = {
87
85
  readonly [K in keyof T]: T[K] extends FullPropType<infer V>
88
- ? V
89
- : T[K] extends PropType<infer V>
90
- ? V
91
- : WechatMiniprogram.Component.PropertyToData<T[K]>
86
+ ? V
87
+ : T[K] extends PropType<infer V>
88
+ ? V
89
+ : WechatMiniprogram.Component.PropertyToData<T[K]>
92
90
  }
93
91
 
94
92
  type RequiredPropertyNames<T> = {
@@ -246,7 +244,7 @@ export function injectMixins (mixins: object | Array<object>, options?: MixinTyp
246
244
  // export function watch (expr: string | (() => any), handler: WatchHandler | WatchOptWithHandler, options?: WatchOpt): () => void
247
245
 
248
246
  interface AnyConstructor {
249
- new (...args: any[]): any
247
+ new(...args: any[]): any
250
248
 
251
249
  prototype: any
252
250
  }
@@ -266,6 +264,7 @@ interface MpxConfig {
266
264
  setDataHandler: (data: object, target: ComponentIns<{}, {}, {}, {}, []>) => any | null
267
265
  forceFlushSync: boolean,
268
266
  webRouteConfig: object,
267
+ webConfig: object,
269
268
  webviewConfig?: WebviewConfig
270
269
  }
271
270
 
@@ -285,9 +284,9 @@ export type Plugin = PluginInstallFunction | {
285
284
  install: PluginInstallFunction
286
285
  }
287
286
 
288
- export type PluginFunction<T extends Plugin> = T extends PluginInstallFunction ? T : T extends { install: infer U } ? U : never;
287
+ export type PluginFunction<T extends Plugin> = T extends PluginInstallFunction ? T : T extends { install: infer U } ? U : never
289
288
 
290
- export type PluginFunctionParams<T extends PluginInstallFunction> = T extends (app: any, ...args: infer P) => any ? P : [];
289
+ export type PluginFunctionParams<T extends PluginInstallFunction> = T extends (app: any, ...args: infer P) => any ? P : []
291
290
 
292
291
  export interface Mpx {
293
292
  getMixin: typeof getMixin
@@ -297,7 +296,7 @@ export interface Mpx {
297
296
  observable: typeof observable
298
297
  watch: typeof watch
299
298
 
300
- use <T extends Plugin = Plugin>(plugin: T, ...rest: PluginFunctionParams<PluginFunction<T>>): Mpx
299
+ use<T extends Plugin = Plugin> (plugin: T, ...rest: PluginFunctionParams<PluginFunction<T>>): Mpx
301
300
 
302
301
  implement (name: string, options?: ImplementOptions): void
303
302
 
@@ -376,8 +375,8 @@ export interface RefUnwrapBailTypes {
376
375
  export type UnwrapRef<T> = T extends ShallowRef<infer V>
377
376
  ? V
378
377
  : T extends Ref<infer V>
379
- ? UnwrapRefSimple<V>
380
- : UnwrapRefSimple<T>
378
+ ? UnwrapRefSimple<V>
379
+ : UnwrapRefSimple<T>
381
380
 
382
381
  export type UnwrapRefSimple<T> = T extends | Function
383
382
  | CollectionTypes
@@ -386,10 +385,10 @@ export type UnwrapRefSimple<T> = T extends | Function
386
385
  | RefUnwrapBailTypes[keyof RefUnwrapBailTypes]
387
386
  ? T
388
387
  : T extends Array<any>
389
- ? { [K in keyof T]: UnwrapRefSimple<T[K]> }
390
- : T extends object & { [ShallowReactiveMarker]?: never } // not a shallowReactive
391
- ? { [P in keyof T]: P extends symbol ? T[P] : UnwrapRef<T[P]> }
392
- : T
388
+ ? { [K in keyof T]: UnwrapRefSimple<T[K]> }
389
+ : T extends object & { [ShallowReactiveMarker]?: never } // not a shallowReactive
390
+ ? { [P in keyof T]: P extends symbol ? T[P] : UnwrapRef<T[P]> }
391
+ : T
393
392
 
394
393
  // If the the type T accepts type "any", output type Y, otherwise output type N.
395
394
  // https://stackoverflow.com/questions/49927523/disallow-call-with-any/49928360#49928360
@@ -426,9 +425,7 @@ export interface ComputedRef<T = any> extends WritableComputedRef<T> {
426
425
  [ComputedRefSymbol]: true
427
426
  }
428
427
 
429
- export interface WritableComputedRef<T> extends Ref<T> {
430
- // readonly effect: ReactiveEffect<T>
431
- }
428
+ export type WritableComputedRef<T> = Ref<T>
432
429
 
433
430
  type WatchCallback<T> = (
434
431
  value: T,
@@ -462,7 +459,6 @@ interface EffectScope {
462
459
  resume (ignoreDirty?: boolean): void
463
460
  }
464
461
 
465
-
466
462
  type StringObj = {
467
463
  [k: string]: string | StringObj
468
464
  }
@@ -489,7 +485,6 @@ interface UseI18n {
489
485
  mergeLocaleMessage (locale: string, messages: StringObj): void
490
486
  }
491
487
 
492
-
493
488
  export function ref<T extends object> (
494
489
  value: T
495
490
  ): [T] extends [Ref] ? T : Ref<UnwrapRef<T>>
@@ -529,7 +524,6 @@ export function computed<T> (
529
524
  options: WritableComputedOptions<T>
530
525
  ): WritableComputedRef<T>
531
526
 
532
-
533
527
  export function watchEffect (
534
528
  effect: (onCleanup: (cleanupFn: () => void) => void) => void,
535
529
  options?: WatchEffectOptions
@@ -545,7 +539,6 @@ export function watchPostEffect (
545
539
  options?: WatchEffectOptions
546
540
  ): void
547
541
 
548
-
549
542
  export function watch<T extends MultiWatchSources> (
550
543
  sources: [...T],
551
544
  callback: WatchCallback<{
@@ -572,13 +565,9 @@ export function watch<T extends Reactive<object>> ( // for reactive value
572
565
  ): () => void
573
566
 
574
567
  export function effectScope (detached?: boolean): EffectScope
575
-
576
568
  export function getCurrentScope (): EffectScope | undefined
577
-
578
569
  export function onScopeDispose (fn: () => void): void
579
-
580
570
  export function set<T extends object> (target: T, key: string | number, value: any): void
581
-
582
571
  export function del<T extends object> (target: T, key: keyof T): void
583
572
 
584
573
  // nextTick
@@ -586,43 +575,25 @@ export function nextTick (fn: () => any): void
586
575
 
587
576
  // lifecycle
588
577
  export function onBeforeMount (callback: () => void): void
589
-
590
578
  export function onMounted (callback: () => void): void
591
-
592
579
  export function onBeforeUpdate (callback: () => void): void
593
-
594
580
  export function onUpdated (callback: () => void): void
595
-
596
581
  export function onBeforeUnmount (callback: () => void): void
597
-
598
582
  export function onUnmounted (callback: () => void): void
599
-
600
583
  export function onLoad<T extends Record<string, string | undefined>> (callback: (query: T) => void): void
601
-
602
- // wechat dose not have generics
603
- // export function onLoad (callback: WechatMiniprogram.Page.ILifetime['onLoad']): void
604
-
605
584
  export function onShow (callback: WechatMiniprogram.Page.ILifetime['onShow']): void
606
-
607
585
  export function onHide (callback: WechatMiniprogram.Page.ILifetime['onHide']): void
608
-
609
586
  export function onResize (callback: WechatMiniprogram.Page.ILifetime['onResize']): void
610
-
611
587
  export function onPullDownRefresh (callback: WechatMiniprogram.Page.ILifetime['onPullDownRefresh']): void
612
-
613
588
  export function onReachBottom (callback: WechatMiniprogram.Page.ILifetime['onReachBottom']): void
614
-
615
589
  export function onShareAppMessage (callback: WechatMiniprogram.Page.ILifetime['onShareAppMessage']): void
616
-
617
590
  export function onShareTimeline (callback: WechatMiniprogram.Page.ILifetime['onShareTimeline']): void
618
-
619
591
  export function onAddToFavorites (callback: WechatMiniprogram.Page.ILifetime['onAddToFavorites']): void
620
-
621
592
  export function onPageScroll (callback: WechatMiniprogram.Page.ILifetime['onPageScroll']): void
622
-
623
593
  export function onTabItemTap (callback: WechatMiniprogram.Page.ILifetime['onTabItemTap']): void
624
-
625
594
  export function onSaveExitState (callback: () => void): void
595
+ export function onServerPrefetch (callback: () => any): void
596
+ export function onReactHooksExec (callback: () => void): void
626
597
 
627
598
  // get instance
628
599
  export function getCurrentInstance<T extends ComponentIns<{}, {}, {}>> (): { proxy: T, [x: string]: any }
@@ -672,6 +643,8 @@ export const ONLOAD: string
672
643
  export const ONSHOW: string
673
644
  export const ONHIDE: string
674
645
  export const ONRESIZE: string
646
+ export const SERVERPREFETCH: string
647
+ export const REACTHOOKSEXEC: string
675
648
 
676
649
  declare global {
677
650
  const defineProps: (<T extends Properties = {}>(props: T) => Readonly<GetPropsType<T>>) & (<T>() => Readonly<T>)
package/@types/node.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- // @ts-ignore
2
1
  declare let global: Record<string, any> // in web, we use global varible to do some things, here to declare
3
2
 
4
3
  type Dict<T> = {
@@ -7,7 +6,6 @@ type Dict<T> = {
7
6
 
8
7
  type EnvType = Dict<string>
9
8
 
10
- // @ts-ignore
11
9
  declare let process: {
12
10
  env: EnvType
13
11
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/core",
3
- "version": "2.9.59",
3
+ "version": "2.9.64",
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.59",
22
+ "@mpxjs/utils": "^2.9.64",
23
23
  "lodash": "^4.1.1",
24
24
  "miniprogram-api-typings": "^3.10.0"
25
25
  },
@@ -31,7 +31,9 @@
31
31
  "@react-navigation/native-stack": "^6.9.26",
32
32
  "react": "*",
33
33
  "react-native": "*",
34
+ "react-native-gesture-handler": "^2.19.0",
34
35
  "react-native-safe-area-context": "^4.10.1",
36
+ "react-native-webview": "^13.10.5",
35
37
  "vue": "^2.7.10",
36
38
  "vue-demi": "^0.14.6",
37
39
  "vue-i18n": "^8.27.2",
@@ -67,6 +69,12 @@
67
69
  },
68
70
  "react-native-safe-area-context": {
69
71
  "optional": true
72
+ },
73
+ "react-native-webview": {
74
+ "optional": true
75
+ },
76
+ "react-native-gesture-handler": {
77
+ "optional": true
70
78
  }
71
79
  },
72
80
  "publishConfig": {
@@ -85,5 +93,5 @@
85
93
  "url": "https://github.com/didi/mpx/issues"
86
94
  },
87
95
  "sideEffects": false,
88
- "gitHead": "aa001c11cc7b21772fc6f9f5bcdd13118fc6d67c"
96
+ "gitHead": "803334dc0e600f219d514c27461aa7663b7a6653"
89
97
  }
@@ -5,7 +5,7 @@ import {
5
5
  import { implemented } from '../core/implement'
6
6
 
7
7
  // 暂不支持的wx选项,后期需要各种花式支持
8
- const unsupported = ['relations', 'moved', 'definitionFilter', 'onShareAppMessage', 'options', 'behaviors', 'externalClasses']
8
+ const unsupported = ['relations', 'moved', 'definitionFilter', 'onShareAppMessage']
9
9
 
10
10
  function convertErrorDesc (key) {
11
11
  error(`Options.${key} is not supported in runtime conversion from wx to react native.`, global.currentResource)
@@ -11,6 +11,7 @@ export const ONSHOW = '__onShow__'
11
11
  export const ONHIDE = '__onHide__'
12
12
  export const ONRESIZE = '__onResize__'
13
13
  export const SERVERPREFETCH = '__serverPrefetch__'
14
+ export const REACTHOOKSEXEC = '__reactHooksExec__'
14
15
 
15
16
  export const INNER_LIFECYCLES = [
16
17
  BEFORECREATE,
@@ -21,6 +22,7 @@ export const INNER_LIFECYCLES = [
21
22
  UPDATED,
22
23
  BEFOREUNMOUNT,
23
24
  SERVERPREFETCH,
25
+ REACTHOOKSEXEC,
24
26
  UNMOUNTED,
25
27
  ONLOAD,
26
28
  ONSHOW,
@@ -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' && key !== 'serverPrefetch' && !componentHooksMap[key]) {
357
+ if (typeof options[key] === 'function' && key !== 'dataFn' && key !== 'setup' && !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
@@ -42,7 +42,8 @@ import {
42
42
  ONLOAD,
43
43
  ONSHOW,
44
44
  ONHIDE,
45
- ONRESIZE
45
+ ONRESIZE,
46
+ REACTHOOKSEXEC
46
47
  } from './innerLifecycle'
47
48
  import contextMap from '../dynamic/vnode/context'
48
49
  import { getAst } from '../dynamic/astCache'
@@ -498,11 +499,28 @@ export default class MpxProxy {
498
499
  return result
499
500
  }
500
501
 
501
- doRenderWithVNode (vnode) {
502
+ doRenderWithVNode (vnode, cb) {
503
+ const renderTask = this.createRenderTask()
504
+ let callback = cb
505
+ // mounted之后才会触发BEFOREUPDATE/UPDATED
506
+ if (this.isMounted()) {
507
+ this.callHook(BEFOREUPDATE)
508
+ callback = () => {
509
+ cb && cb()
510
+ this.callHook(UPDATED)
511
+ renderTask && renderTask.resolve()
512
+ }
513
+ }
502
514
  if (!this._vnode) {
503
- this.target.__render({ r: vnode })
515
+ this._vnode = diffAndCloneA(vnode).clone
516
+ pauseTracking()
517
+ // 触发渲染时暂停数据响应追踪,避免误收集到子组件的数据依赖
518
+ this.target.__render({ r: vnode }, callback)
519
+ resetTracking()
504
520
  } else {
505
- let diffPath = diffAndCloneA(vnode, this._vnode).diffData
521
+ const result = diffAndCloneA(vnode, this._vnode)
522
+ this._vnode = result.clone
523
+ let diffPath = result.diffData
506
524
  if (!isEmptyObject(diffPath)) {
507
525
  // 构造 diffPath 数据
508
526
  diffPath = Object.keys(diffPath).reduce((preVal, curVal) => {
@@ -510,11 +528,11 @@ export default class MpxProxy {
510
528
  preVal[key] = diffPath[curVal]
511
529
  return preVal
512
530
  }, {})
513
- this.target.__render(diffPath)
531
+ pauseTracking()
532
+ this.target.__render(diffPath, callback)
533
+ resetTracking()
514
534
  }
515
535
  }
516
- // 缓存本地的 vnode 用以下一次 diff
517
- this._vnode = diffAndCloneA(vnode).clone
518
536
  }
519
537
 
520
538
  doRender (data, cb) {
@@ -734,6 +752,7 @@ export const onShow = createHook(ONSHOW)
734
752
  export const onHide = createHook(ONHIDE)
735
753
  export const onResize = createHook(ONRESIZE)
736
754
  export const onServerPrefetch = createHook(SERVERPREFETCH)
755
+ export const onReactHooksExec = createHook(REACTHOOKSEXEC)
737
756
  export const onPullDownRefresh = createHook('__onPullDownRefresh__')
738
757
  export const onReachBottom = createHook('__onReachBottom__')
739
758
  export const onShareAppMessage = createHook('__onShareAppMessage__')
package/src/index.js CHANGED
@@ -29,11 +29,12 @@ export {
29
29
  UPDATED,
30
30
  BEFOREUNMOUNT,
31
31
  UNMOUNTED,
32
- SERVERPREFETCH,
33
32
  ONLOAD,
34
33
  ONSHOW,
35
34
  ONHIDE,
36
- ONRESIZE
35
+ ONRESIZE,
36
+ SERVERPREFETCH,
37
+ REACTHOOKSEXEC
37
38
  } from './core/innerLifecycle'
38
39
 
39
40
  export {
@@ -43,7 +44,6 @@ export {
43
44
  onUpdated,
44
45
  onBeforeUnmount,
45
46
  onUnmounted,
46
- onServerPrefetch,
47
47
  onLoad,
48
48
  onShow,
49
49
  onHide,
@@ -55,7 +55,9 @@ export {
55
55
  onAddToFavorites,
56
56
  onPageScroll,
57
57
  onTabItemTap,
58
- onSaveExitState
58
+ onSaveExitState,
59
+ onServerPrefetch,
60
+ onReactHooksExec
59
61
  } from './core/proxy'
60
62
 
61
63
  export { getMixin } from './core/mergeOptions'
@@ -136,19 +138,21 @@ Mpx.config = {
136
138
  ignoreProxyWhiteList: ['id', 'dataset', 'data'],
137
139
  observeClassInstance: false,
138
140
  errorHandler: null,
141
+ warnHandler: null,
139
142
  proxyEventHandler: null,
140
143
  setDataHandler: null,
141
144
  forceFlushSync: false,
142
145
  webRouteConfig: {},
146
+ webConfig: {},
143
147
  /*
144
148
  支持两个属性
145
149
  hostWhitelists Array 类型 支持h5域名白名单安全校验
146
150
  apiImplementations webview JSSDK接口 例如getlocation
147
151
  */
148
152
  webviewConfig: {},
149
- /**
150
- * react-native 相关配置,用于挂载事件等,如 onShareAppMessage
151
- */
153
+ /**
154
+ * react-native 相关配置,用于挂载事件等,如 onShareAppMessage
155
+ */
152
156
  rnConfig: {}
153
157
  }
154
158
 
@@ -1,14 +1,8 @@
1
- import { warn, type } from '@mpxjs/utils'
2
1
  export default function directiveHelperMixin () {
3
2
  return {
4
3
  methods: {
5
4
  __getWxKey (item, key) {
6
- const value = key === '*this' ? item : item[key]
7
- if (typeof value === 'string' || typeof value === 'number') {
8
- return value
9
- } else {
10
- warn(`wx:key's value should return a string or a number, received: ${type(value)}`, this.__mpxProxy.options.mpxFileResource)
11
- }
5
+ return key === '*this' ? item : item[key]
12
6
  }
13
7
  }
14
8
  }
@@ -14,13 +14,13 @@ import { dynamicRefsMixin, dynamicRenderHelperMixin, dynamicSlotMixin } from '..
14
14
  import styleHelperMixin from './styleHelperMixin'
15
15
  import directiveHelperMixin from './directiveHelperMixin'
16
16
 
17
- export default function getBuiltInMixins (options, type) {
17
+ export default function getBuiltInMixins ({ type, rawOptions = {} }) {
18
18
  let bulitInMixins
19
19
  if (__mpx_mode__ === 'ios' || __mpx_mode__ === 'android') {
20
20
  bulitInMixins = [
21
21
  proxyEventMixin(),
22
22
  directiveHelperMixin(),
23
- styleHelperMixin(type),
23
+ styleHelperMixin(),
24
24
  refsMixin(),
25
25
  i18nMixin()
26
26
  ]
@@ -46,7 +46,7 @@ export default function getBuiltInMixins (options, type) {
46
46
  relationsMixin(type)
47
47
  ]
48
48
  // 此为纯增强类mixins,原生模式下不需要注入
49
- if (!options.__nativeRender__) {
49
+ if (!rawOptions.__nativeRender__) {
50
50
  bulitInMixins = bulitInMixins.concat([
51
51
  renderHelperMixin(),
52
52
  showMixin(type),
@@ -1,76 +1,55 @@
1
- import { BEFORECREATE, CREATED } from '../../core/innerLifecycle'
1
+ import { BEFORECREATE } from '../../core/innerLifecycle'
2
2
  import { createSelectorQuery } from '@mpxjs/api-proxy'
3
- import { computed } from '../../observer/computed'
4
3
 
5
4
  export default function getRefsMixin () {
6
5
  return {
7
6
  [BEFORECREATE] () {
8
7
  this.__refs = {}
9
8
  this.$refs = {}
10
- },
11
- // __getRefs强依赖数据响应,需要在CREATED中执行
12
- [CREATED] () {
13
9
  this.__getRefs()
14
10
  },
15
11
  methods: {
16
12
  __getRefs () {
17
13
  const refs = this.__getRefsData() || []
18
14
  const target = this
19
- this.__selectorMap = computed(() => {
20
- const selectorMap = {}
21
- refs.forEach(({ key, type, sKeys }) => {
22
- // sKeys 是使用 wx:ref 没有值的标记场景,支持运行时的 createSelectorQuery 的使用
23
- if (sKeys) {
24
- sKeys.forEach((item = {}) => {
25
- const computedKey = item.key
26
- const prefix = item.prefix
27
- const selectors = this[computedKey] || ''
28
- selectors.trim().split(/\s+/).forEach(item => {
29
- const selector = prefix + item
30
- selectorMap[selector] = selectorMap[selector] || []
31
- selectorMap[selector].push({ type, key })
32
- })
33
- })
34
- } else {
35
- selectorMap[key] = selectorMap[key] || []
36
- selectorMap[key].push({ type, key })
15
+ refs.forEach(({ key, type, all }) => {
16
+ Object.defineProperty(this.$refs, key, {
17
+ enumerable: true,
18
+ configurable: true,
19
+ get () {
20
+ if (type === 'component') {
21
+ return all ? target.selectAllComponents(key) : target.selectComponent(key)
22
+ } else {
23
+ return createSelectorQuery().in(target).select(key, all)
24
+ }
37
25
  }
38
26
  })
39
- return selectorMap
40
27
  })
41
- refs.forEach(({ key, type, all, sKeys }) => {
42
- // 如果没有 sKey 说明使用的是 wx:ref="xxx" 的场景
43
- if (!sKeys) {
44
- Object.defineProperty(this.$refs, key, {
45
- enumerable: true,
46
- configurable: true,
47
- get () {
48
- const refs = target.__refs[key] || []
49
- if (type === 'component') {
50
- return all ? refs : refs[0]
51
- } else {
52
- return createSelectorQuery().in(target).select(key, all)
53
- }
28
+ },
29
+ __getRefVal (type, selectorsConf) {
30
+ return (instance) => {
31
+ if (instance) {
32
+ selectorsConf.forEach((item = []) => {
33
+ const [prefix, selectors = ''] = item
34
+ if (selectors) {
35
+ selectors.trim().split(/\s+/).forEach(selector => {
36
+ const refKey = prefix + selector
37
+ this.__refs[refKey] = this.__refs[refKey] || []
38
+ this.__refs[refKey].push({ type, instance })
39
+ })
54
40
  }
55
41
  })
56
42
  }
57
- })
58
- },
59
- __getRefVal (key) {
60
- if (!this.__refs[key]) {
61
- this.__refs[key] = []
62
43
  }
63
- return (instance) => instance && this.__refs[key].push(instance)
64
44
  },
65
45
  __selectRef (selector, refType, all = false) {
66
- const splitedSelector = selector.match(/(#|\.)?\w+/g) || []
46
+ const splitedSelector = selector.match(/(#|\.)?[^.#]+/g) || []
67
47
  const refsArr = splitedSelector.map(selector => {
68
- const selectorMap = this.__selectorMap?.value[selector] || []
48
+ const refs = this.__refs[selector] || []
69
49
  const res = []
70
- selectorMap.forEach(({ type, key }) => {
50
+ refs.forEach(({ type, instance }) => {
71
51
  if (type === refType) {
72
- const _refs = this.__refs[key] || []
73
- res.push(..._refs)
52
+ res.push(instance)
74
53
  }
75
54
  })
76
55
  return res
@@ -1,8 +1,59 @@
1
- import { isObject, isArray, dash2hump, isFunction } from '@mpxjs/utils'
2
- import { Dimensions } from 'react-native'
1
+ import { isObject, isArray, dash2hump, isFunction, cached } from '@mpxjs/utils'
2
+ import { Dimensions, StyleSheet } from 'react-native'
3
3
 
4
- function concat (a, b) {
5
- return a ? b ? (a + ' ' + b) : a : (b || '')
4
+ function rpx (value) {
5
+ const { width } = Dimensions.get('screen')
6
+ // rn 单位 dp = 1(css)px = 1 物理像素 * pixelRatio(像素比)
7
+ // px = rpx * (750 / 屏幕宽度)
8
+ return value * width / 750
9
+ }
10
+ function vw (value) {
11
+ const { width } = Dimensions.get('screen')
12
+ return value * width / 100
13
+ }
14
+ function vh (value) {
15
+ const { height } = Dimensions.get('screen')
16
+ return value * height / 100
17
+ }
18
+
19
+ global.__unit = {
20
+ rpx,
21
+ vw,
22
+ vh
23
+ }
24
+ global.__hairlineWidth = StyleSheet.hairlineWidth
25
+
26
+ const escapeReg = /[()[\]{}#!.:,%'"+$]/g
27
+ const escapeMap = {
28
+ '(': '_pl_',
29
+ ')': '_pr_',
30
+ '[': '_bl_',
31
+ ']': '_br_',
32
+ '{': '_cl_',
33
+ '}': '_cr_',
34
+ '#': '_h_',
35
+ '!': '_i_',
36
+ '/': '_s_',
37
+ '.': '_d_',
38
+ ':': '_c_',
39
+ ',': '_2c_',
40
+ '%': '_p_',
41
+ '\'': '_q_',
42
+ '"': '_dq_',
43
+ '+': '_a_',
44
+ $: '_si_'
45
+ }
46
+
47
+ const mpEscape = cached((str) => {
48
+ return str.replace(escapeReg, function (match) {
49
+ if (escapeMap[match]) return escapeMap[match]
50
+ // unknown escaped
51
+ return '_u_'
52
+ })
53
+ })
54
+
55
+ function concat (a = '', b = '') {
56
+ return a ? b ? (a + ' ' + b) : a : b
6
57
  }
7
58
 
8
59
  function stringifyArray (value) {
@@ -41,10 +92,12 @@ function stringifyDynamicClass (value) {
41
92
 
42
93
  const listDelimiter = /;(?![^(]*[)])/g
43
94
  const propertyDelimiter = /:(.+)/
44
- const rpxRegExp = /^\s*(-?\d+(\.\d+)?)rpx\s*$/
45
- const pxRegExp = /^\s*(-?\d+(\.\d+)?)(px)?\s*$/
95
+ const unitRegExp = /^\s*(-?\d+(?:\.\d+)?)(rpx|vw|vh)\s*$/
96
+ const numberRegExp = /^\s*(-?\d+(\.\d+)?)(px)?\s*$/
97
+ const hairlineRegExp = /^\s*hairlineWidth\s*$/
98
+ const varRegExp = /^--/
46
99
 
47
- function parseStyleText (cssText) {
100
+ const parseStyleText = cached((cssText = '') => {
48
101
  const res = {}
49
102
  const arr = cssText.split(listDelimiter)
50
103
  for (let i = 0; i < arr.length; i++) {
@@ -52,13 +105,14 @@ function parseStyleText (cssText) {
52
105
  if (item) {
53
106
  const tmp = item.split(propertyDelimiter)
54
107
  if (tmp.length > 1) {
55
- const k = dash2hump(tmp[0].trim())
108
+ let k = tmp[0].trim()
109
+ k = varRegExp.test(k) ? k : dash2hump(k)
56
110
  res[k] = tmp[1].trim()
57
111
  }
58
112
  }
59
113
  }
60
114
  return res
61
- }
115
+ })
62
116
 
63
117
  function normalizeDynamicStyle (value) {
64
118
  if (!value) return {}
@@ -79,65 +133,61 @@ function mergeObjectArray (arr) {
79
133
  return res
80
134
  }
81
135
 
82
- function transformStyleObj (context, styleObj) {
136
+ function transformStyleObj (styleObj) {
83
137
  const keys = Object.keys(styleObj)
84
138
  const transformed = {}
85
139
  keys.forEach((prop) => {
86
- // todo 检测不支持的prop
87
140
  let value = styleObj[prop]
88
141
  let matched
89
- if ((matched = pxRegExp.exec(value))) {
142
+ if ((matched = numberRegExp.exec(value))) {
90
143
  value = +matched[1]
91
- } else if ((matched = rpxRegExp.exec(value))) {
92
- value = context.__rpx(+matched[1])
144
+ } else if ((matched = unitRegExp.exec(value))) {
145
+ value = global.__unit[matched[2]](+matched[1])
146
+ } else if (hairlineRegExp.test(value)) {
147
+ value = StyleSheet.hairlineWidth
93
148
  }
94
- // todo 检测不支持的value
95
149
  transformed[prop] = value
96
150
  })
97
151
  return transformed
98
152
  }
99
153
 
100
- export default function styleHelperMixin (type) {
154
+ export default function styleHelperMixin () {
101
155
  return {
102
156
  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
157
  __getClass (staticClass, dynamicClass) {
110
158
  return concat(staticClass, stringifyDynamicClass(dynamicClass))
111
159
  },
112
- __getStyle (staticClass, dynamicClass, staticStyle, dynamicStyle, show) {
113
- // todo 每次返回新对象会导致react memo优化失效,需要考虑优化手段
114
- const result = []
160
+ __getStyle (staticClass, dynamicClass, staticStyle, dynamicStyle, hide) {
161
+ const result = {}
115
162
  const classMap = {}
116
- if (type === 'page' && isFunction(global.__getAppClassMap)) {
117
- Object.assign(classMap, global.__getAppClassMap.call(this))
163
+ // todo 全局样式在每个页面和组件中生效,以支持全局原子类,后续支持样式模块复用后可考虑移除
164
+ if (isFunction(global.__getAppClassMap)) {
165
+ Object.assign(classMap, global.__getAppClassMap())
118
166
  }
119
167
  if (isFunction(this.__getClassMap)) {
120
168
  Object.assign(classMap, this.__getClassMap())
121
169
  }
170
+
122
171
  if (staticClass || dynamicClass) {
123
- const classString = concat(staticClass, stringifyDynamicClass(dynamicClass))
172
+ // todo 当前为了复用小程序unocss产物,暂时进行mpEscape,等后续正式支持unocss后可不进行mpEscape
173
+ const classString = mpEscape(concat(staticClass, stringifyDynamicClass(dynamicClass)))
124
174
  classString.split(/\s+/).forEach((className) => {
125
175
  if (classMap[className]) {
126
- result.push(classMap[className])
127
- } else if (this.props[className]) {
128
- // externalClasses必定以数组形式传递下来
129
- result.push(...this.props[className])
176
+ Object.assign(result, classMap[className])
177
+ } else if (this.props[className] && isObject(this.props[className])) {
178
+ // externalClasses必定以对象形式传递下来
179
+ Object.assign(result, this.props[className])
130
180
  }
131
181
  })
132
182
  }
133
183
 
134
184
  if (staticStyle || dynamicStyle) {
135
- const styleObj = Object.assign(parseStyleText(staticStyle), normalizeDynamicStyle(dynamicStyle))
136
- result.push(transformStyleObj(this, styleObj))
185
+ const styleObj = Object.assign({}, parseStyleText(staticStyle), normalizeDynamicStyle(dynamicStyle))
186
+ Object.assign(result, transformStyleObj(styleObj))
137
187
  }
138
188
 
139
- if (show === false) {
140
- result.push({
189
+ if (hide) {
190
+ Object.assign(result, {
141
191
  display: 'none'
142
192
  })
143
193
  }
@@ -133,7 +133,7 @@ export default function createApp (option, config = {}) {
133
133
  global.__mpxAppFocusedState.value = `resize${count++}`
134
134
  })
135
135
  return () => {
136
- changeSubscription()
136
+ changeSubscription && changeSubscription.remove()
137
137
  resizeSubScription && resizeSubScription.remove()
138
138
  }
139
139
  }, [])
@@ -58,7 +58,7 @@ export default function createFactory (type) {
58
58
  // 不接受mixin中的setup配置
59
59
  // 注入内建的mixins, 内建mixin是按原始平台编写的,所以合并规则和rootMixins保持一致
60
60
  // 将合并后的用户定义的rawOptions传入获取当前应该注入的内建mixins
61
- rawOptions.mixins = getBuiltInMixins(rawOptions, type)
61
+ rawOptions.mixins = getBuiltInMixins({ type, rawOptions, currentInject })
62
62
  const defaultOptions = getDefaultOptions({ type, rawOptions, currentInject })
63
63
  if (__mpx_mode__ === 'web' || __mpx_mode__ === 'ios' || __mpx_mode__ === 'android') {
64
64
  global.__mpxOptionsMap = global.__mpxOptionsMap || {}
@@ -1,11 +1,11 @@
1
- import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, createElement, memo, forwardRef, useImperativeHandle, useContext, createContext, Fragment } from 'react'
1
+ import { useEffect, useLayoutEffect, useSyncExternalStore, useRef, useMemo, 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, error, getByPath, collectDataset } from '@mpxjs/utils'
6
+ import { hasOwn, isFunction, noop, isObject, error, getByPath, collectDataset, hump2dash } from '@mpxjs/utils'
7
7
  import MpxProxy from '../../../core/proxy'
8
- import { BEFOREUPDATE, ONLOAD, UPDATED, ONSHOW, ONHIDE, ONRESIZE } from '../../../core/innerLifecycle'
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
11
  import { createSelectorQuery } from '@mpxjs/api-proxy'
@@ -24,20 +24,7 @@ function getSystemInfo () {
24
24
  }
25
25
  }
26
26
 
27
- function getRootProps (props) {
28
- const rootProps = {}
29
- for (const key in props) {
30
- if (hasOwn(props, key)) {
31
- const match = /^(bind|catch|capture-bind|capture-catch|style):?(.*?)(?:\.(.*))?$/.exec(key)
32
- if (match) {
33
- rootProps[key] = props[key]
34
- }
35
- }
36
- }
37
- return rootProps
38
- }
39
-
40
- function createEffect (proxy, components, props) {
27
+ function createEffect (proxy, components) {
41
28
  const update = proxy.update = () => {
42
29
  // pre render for props update
43
30
  if (proxy.propsUpdatedFlag) {
@@ -57,56 +44,80 @@ function createEffect (proxy, components, props) {
57
44
  return components[tagName] || getByPath(ReactNative, tagName)
58
45
  }
59
46
  proxy.effect = new ReactiveEffect(() => {
60
- return proxy.target.__injectedRender(createElement, getComponent, getRootProps(props))
47
+ // reset instance
48
+ proxy.target.__resetInstance()
49
+ return proxy.target.__injectedRender(createElement, getComponent)
61
50
  }, () => queueJob(update), proxy.scope)
62
51
  }
63
52
 
64
- function createInstance ({ propsRef, type, rawOptions, currentInject, validProps, components }) {
53
+ function getRootProps (props) {
54
+ const rootProps = {}
55
+ for (const key in props) {
56
+ if (hasOwn(props, key)) {
57
+ const match = /^(bind|catch|capture-bind|capture-catch|style|enable-var):?(.*?)(?:\.(.*))?$/.exec(key)
58
+ if (match) {
59
+ rootProps[key] = props[key]
60
+ }
61
+ }
62
+ }
63
+ return rootProps
64
+ }
65
+
66
+ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps, components, pageId }) {
65
67
  const instance = Object.create({
66
68
  setData (data, callback) {
67
69
  return this.__mpxProxy.forceUpdate(data, { sync: true }, callback)
68
70
  },
71
+ getPageId () {
72
+ return pageId
73
+ },
69
74
  __getProps () {
70
- const propsData = {}
71
75
  const props = propsRef.current
76
+ const propsData = {}
72
77
  Object.keys(validProps).forEach((key) => {
73
78
  if (hasOwn(props, key)) {
74
79
  propsData[key] = props[key]
75
80
  } else {
76
- let field = validProps[key]
77
- if (isFunction(field) || field === null) {
78
- field = {
79
- type: field
81
+ const altKey = hump2dash(key)
82
+ if (hasOwn(props, altKey)) {
83
+ propsData[key] = props[altKey]
84
+ } else {
85
+ let field = validProps[key]
86
+ if (isFunction(field) || field === null) {
87
+ field = {
88
+ type: field
89
+ }
80
90
  }
91
+ // 处理props默认值
92
+ propsData[key] = field.value
81
93
  }
82
- // 处理props默认值
83
- propsData[key] = field.value
84
94
  }
85
95
  })
86
96
  return propsData
87
97
  },
98
+ __resetInstance () {
99
+ this.__refs = {}
100
+ this.__dispatchedSlotSet = new WeakSet()
101
+ },
88
102
  __getSlot (name) {
89
103
  const { children } = propsRef.current
90
104
  if (children) {
91
105
  const result = []
92
106
  if (Array.isArray(children)) {
93
107
  children.forEach(child => {
94
- if (child && child.props && child.props.slot === name) {
108
+ if (child?.props?.slot === name) {
95
109
  result.push(child)
96
110
  }
97
111
  })
98
112
  } else {
99
- if (children && children.props && children.props.slot === name) {
113
+ if (children?.props?.slot === name) {
100
114
  result.push(children)
101
115
  }
102
116
  }
103
117
  return result.filter(item => {
104
- if (this.__dispatchedSlotSet.has(item)) {
105
- return false
106
- } else {
107
- this.__dispatchedSlotSet.add(item)
108
- return true
109
- }
118
+ if (!isObject(item) || this.__dispatchedSlotSet.has(item)) return false
119
+ this.__dispatchedSlotSet.add(item)
120
+ return true
110
121
  })
111
122
  }
112
123
  return null
@@ -204,17 +215,13 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
204
215
  const proxy = instance.__mpxProxy = new MpxProxy(rawOptions, instance)
205
216
  proxy.created()
206
217
 
207
- if (type === 'page') {
208
- proxy.callHook(ONLOAD, [props.route.params || {}])
209
- }
210
-
211
218
  Object.assign(proxy, {
212
219
  onStoreChange: null,
213
220
  // eslint-disable-next-line symbol-description
214
221
  stateVersion: Symbol(),
215
222
  subscribe: (onStoreChange) => {
216
223
  if (!proxy.effect) {
217
- createEffect(proxy, components, propsRef.current)
224
+ createEffect(proxy, components)
218
225
  // eslint-disable-next-line symbol-description
219
226
  proxy.stateVersion = Symbol()
220
227
  }
@@ -231,7 +238,7 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
231
238
  })
232
239
  // react数据响应组件更新管理器
233
240
  if (!proxy.effect) {
234
- createEffect(proxy, components, propsRef.current)
241
+ createEffect(proxy, components)
235
242
  }
236
243
 
237
244
  return instance
@@ -253,7 +260,7 @@ function hasPageHook (mpxProxy, hookNames) {
253
260
  })
254
261
  }
255
262
 
256
- const routeContext = createContext(null)
263
+ const RouteContext = createContext(null)
257
264
 
258
265
  const triggerPageStatusHook = (mpxProxy, event) => {
259
266
  mpxProxy.callHook(event === 'show' ? ONSHOW : ONHIDE)
@@ -277,13 +284,7 @@ const triggerResizeEvent = (mpxProxy) => {
277
284
  }
278
285
  }
279
286
 
280
- function usePageContext (mpxProxy, instance) {
281
- const { pageId } = useContext(routeContext) || {}
282
-
283
- instance.getPageId = () => {
284
- return pageId
285
- }
286
-
287
+ function usePageEffect (mpxProxy, pageId) {
287
288
  useEffect(() => {
288
289
  let unWatch
289
290
  const hasShowHook = hasPageHook(mpxProxy, [ONSHOW, 'show'])
@@ -300,7 +301,6 @@ function usePageContext (mpxProxy, instance) {
300
301
  })
301
302
  }
302
303
  }
303
-
304
304
  return () => {
305
305
  unWatch && unWatch()
306
306
  }
@@ -343,45 +343,53 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
343
343
  const validProps = Object.assign({}, rawOptions.props, rawOptions.properties)
344
344
  const defaultOptions = memo(forwardRef((props, ref) => {
345
345
  const instanceRef = useRef(null)
346
- const propsRef = useRef(props)
346
+ const propsRef = useRef(null)
347
+ const pageId = useContext(RouteContext)
348
+ propsRef.current = props
347
349
  let isFirst = false
348
350
  if (!instanceRef.current) {
349
351
  isFirst = true
350
- instanceRef.current = createInstance({ propsRef, type, rawOptions, currentInject, validProps, components })
352
+ instanceRef.current = createInstance({ propsRef, type, rawOptions, currentInject, validProps, components, pageId })
351
353
  }
352
354
  const instance = instanceRef.current
353
- // reset instance
354
- instance.__refs = {}
355
- instance.__dispatchedSlotSet = new WeakSet()
356
355
  useImperativeHandle(ref, () => {
357
356
  return instance
358
357
  })
359
- const proxy = instance.__mpxProxy
360
358
 
361
- if (!isFirst) {
362
- // 处理props更新
363
- propsRef.current = props
364
- Object.keys(props).forEach(key => {
365
- if (hasOwn(validProps, key)) {
366
- instance[key] = props[key]
367
- }
368
- })
369
- proxy.propsUpdated()
370
- }
359
+ const proxy = instance.__mpxProxy
371
360
 
372
- usePageContext(proxy, instance)
361
+ proxy.callHook(REACTHOOKSEXEC)
373
362
 
374
363
  useEffect(() => {
364
+ if (!isFirst) {
365
+ // 处理props更新
366
+ Object.keys(validProps).forEach((key) => {
367
+ if (hasOwn(props, key)) {
368
+ instance[key] = props[key]
369
+ } else {
370
+ const altKey = hump2dash(key)
371
+ if (hasOwn(props, altKey)) {
372
+ instance[key] = props[altKey]
373
+ }
374
+ }
375
+ })
376
+ }
375
377
  if (proxy.pendingUpdatedFlag) {
376
378
  proxy.pendingUpdatedFlag = false
377
379
  proxy.callHook(UPDATED)
378
380
  }
379
381
  })
380
382
 
383
+ usePageEffect(proxy, pageId)
384
+
381
385
  useEffect(() => {
386
+ if (type === 'page') {
387
+ proxy.callHook(ONLOAD, [props.route.params || {}])
388
+ }
382
389
  proxy.mounted()
383
390
  return () => {
384
391
  proxy.unmounted()
392
+ proxy.target.__resetInstance()
385
393
  if (type === 'page') {
386
394
  delete global.__mpxPagesMap[props.route.key]
387
395
  }
@@ -390,11 +398,18 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
390
398
 
391
399
  useSyncExternalStore(proxy.subscribe, proxy.getSnapshot)
392
400
 
393
- return proxy.effect.run()
401
+ const root = rawOptions.options?.disableMemo ? proxy.effect.run() : useMemo(() => proxy.effect.run(), [proxy.stateVersion])
402
+ if (root) {
403
+ const rootProps = getRootProps(props)
404
+ rootProps.style = { ...root.props.style, ...rootProps.style }
405
+ // update root props
406
+ return cloneElement(root, rootProps)
407
+ }
408
+ return root
394
409
  }))
395
410
 
396
411
  if (type === 'page') {
397
- const { Provider, useSafeAreaInsets } = global.__navigationHelper
412
+ const { Provider, useSafeAreaInsets, GestureHandlerRootView } = global.__navigationHelper
398
413
  const pageConfig = Object.assign({}, global.__mpxPageConfig, currentInject.pageConfig)
399
414
  const Page = ({ navigation, route }) => {
400
415
  const currentPageId = useMemo(() => ++pageId, [])
@@ -411,31 +426,30 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
411
426
  })
412
427
  }, [])
413
428
 
414
- const insets = useSafeAreaInsets()
415
- const safeAreaPadding = {
416
- paddingTop: insets.top,
417
- paddingLeft: insets.left
418
- }
429
+ navigation.insets = useSafeAreaInsets()
419
430
 
420
- return createElement(Provider,
421
- null,
422
- createElement(ReactNative.View,
423
- {
424
- style: {
425
- ...pageConfig.navigationStyle === 'custom' && safeAreaPadding,
426
- ...ReactNative.StyleSheet.absoluteFillObject,
427
- backgroundColor: pageConfig.backgroundColor || '#ffffff'
428
- }
431
+ return createElement(GestureHandlerRootView,
432
+ {
433
+ style: {
434
+ flex: 1,
435
+ backgroundColor: pageConfig.backgroundColor || '#ffffff'
429
436
  },
430
- createElement(routeContext.Provider,
437
+ onLayout (e) {
438
+ navigation.layout = e.nativeEvent.layout
439
+ }
440
+ },
441
+ // todo custom portal host for active route
442
+ createElement(Provider,
443
+ null,
444
+ createElement(RouteContext.Provider,
431
445
  {
432
- value: { pageId: currentPageId }
446
+ value: currentPageId
433
447
  },
434
448
  createElement(defaultOptions,
435
449
  {
436
450
  navigation,
437
451
  route,
438
- pageConfig
452
+ id: currentPageId
439
453
  }
440
454
  )
441
455
  )
@@ -5,7 +5,9 @@ import {
5
5
  ONSHOW,
6
6
  ONHIDE,
7
7
  ONLOAD,
8
- ONRESIZE
8
+ ONRESIZE,
9
+ SERVERPREFETCH,
10
+ REACTHOOKSEXEC
9
11
  } from '../../../core/innerLifecycle'
10
12
 
11
13
  const APP_HOOKS = [
@@ -16,6 +18,7 @@ const APP_HOOKS = [
16
18
  'onPageNotFound',
17
19
  'onUnhandledRejection',
18
20
  'onThemeChange',
21
+ 'onSSRAppCreated',
19
22
  'onAppInit'
20
23
  ]
21
24
 
@@ -43,7 +46,9 @@ const COMPONENT_HOOKS = [
43
46
  'moved',
44
47
  'detached',
45
48
  'pageShow',
46
- 'pageHide'
49
+ 'pageHide',
50
+ 'serverPrefetch',
51
+ 'reactHooksExec'
47
52
  ]
48
53
 
49
54
  export const lifecycleProxyMap = {
@@ -54,7 +59,9 @@ export const lifecycleProxyMap = {
54
59
  [ONSHOW]: ['pageShow', 'onShow'],
55
60
  [ONHIDE]: ['pageHide', 'onHide'],
56
61
  [ONLOAD]: ['onLoad'],
57
- [ONRESIZE]: ['onResize']
62
+ [ONRESIZE]: ['onResize'],
63
+ [SERVERPREFETCH]: ['serverPrefetch'],
64
+ [REACTHOOKSEXEC]: ['reactHooksExec']
58
65
  }
59
66
 
60
67
  export const LIFECYCLE = {