@mpxjs/core 2.8.40-test → 2.8.40-test.2

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/index.d.ts CHANGED
@@ -24,25 +24,33 @@ type UnionToIntersection<U> = (U extends any
24
24
  ? (k: U) => void
25
25
  : never) extends ((k: infer I) => void)
26
26
  ? I
27
- : never;
27
+ : never
28
28
 
29
- type ArrayType<T extends any[]> = T extends Array<infer R> ? R : never;
29
+ type ArrayType<T extends any[]> = T extends Array<infer R> ? R : never
30
30
 
31
31
  // Mpx types
32
32
  type Data = object | (() => object)
33
33
 
34
- type PropConstructor<T = any> = {
35
- new (...args: any[]): T & {};
36
- } | {
37
- (): T;
38
- }
39
-
40
- export type PropType<T> = PropConstructor<T>
34
+ export type PropType<T> = {
35
+ __type: T
36
+ } & (
37
+ T extends String
38
+ ? StringConstructor
39
+ : 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
48
+ )
41
49
 
42
50
  type FullPropType<T> = {
43
- type: PropType<T>;
44
- value?: T;
45
- optionalTypes?: PropType<T>[];
51
+ type: PropType<T>
52
+ value?: T
53
+ optionalTypes?: WechatMiniprogram.Component.ShortProperty[]
46
54
  }
47
55
 
48
56
  interface Properties {
@@ -75,27 +83,17 @@ interface WatchField {
75
83
 
76
84
  type GetDataType<T> = T extends () => any ? ReturnType<T> : T
77
85
 
78
- type PropValueType<Def> = Def extends {
79
- type: (...args: any[]) => infer T;
80
- optionalType?: ((...args: any[]) => infer T)[];
81
- value?: infer T;
82
- }
83
- ? T
84
- : Def extends (...args: any[]) => infer T
85
- ? T
86
- : Def extends FullPropType<infer T>
87
- ? T
88
- : Def extends PropType<infer T>
89
- ? T
90
- : any;
91
-
92
- type GetPropsType<T> = {
93
- readonly [K in keyof T]: PropValueType<T[K]>
86
+ type GetPropsType<T extends Properties> = {
87
+ 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]>
94
92
  }
95
93
 
96
94
  type RequiredPropertyNames<T> = {
97
95
  [K in keyof T]-?: T[K] extends undefined ? never : K
98
- }[keyof T];
96
+ }[keyof T]
99
97
 
100
98
  type RequiredPropertiesForUnion<T> = T extends object ? Pick<T, RequiredPropertyNames<T>> : never
101
99
 
@@ -126,7 +124,7 @@ interface Context {
126
124
  createIntersectionObserver: WechatMiniprogram.Component.InstanceMethods<Record<string, any>>['createIntersectionObserver']
127
125
  }
128
126
 
129
- interface ComponentOpt<D, P, C, M, Mi extends Array<any>, S extends Record<any, any>> extends Partial<WechatMiniprogram.Component.Lifetimes & WechatMiniprogram.Component.OtherOption> {
127
+ interface ComponentOpt<D extends Data, P extends Properties, C, M extends Methods, Mi extends Array<any>, S extends Record<any, any>> extends Partial<WechatMiniprogram.Component.Lifetimes & WechatMiniprogram.Component.OtherOption> {
130
128
  data?: D
131
129
  properties?: P
132
130
  computed?: C
@@ -144,7 +142,7 @@ interface ComponentOpt<D, P, C, M, Mi extends Array<any>, S extends Record<any,
144
142
  [index: string]: any
145
143
  }
146
144
 
147
- type PageOpt<D, P, C, M, Mi extends Array<any>, S extends Record<any, any>> =
145
+ type PageOpt<D extends Data, P extends Properties, C, M extends Methods, Mi extends Array<any>, S extends Record<any, any>> =
148
146
  ComponentOpt<D, P, C, M, Mi, S>
149
147
  & Partial<WechatMiniprogram.Page.ILifetime>
150
148
 
@@ -281,11 +279,11 @@ interface ImplementOptions {
281
279
 
282
280
  export function toPureObject<T extends object> (obj: T): T
283
281
 
284
- declare type PluginInstallFunction = (app: Mpx, ...options: any[]) => any;
282
+ declare type PluginInstallFunction = (app: Mpx, ...options: any[]) => any
285
283
 
286
284
  export type Plugin = PluginInstallFunction | {
287
- install: PluginInstallFunction;
288
- };
285
+ install: PluginInstallFunction
286
+ }
289
287
 
290
288
  export interface Mpx {
291
289
  getMixin: typeof getMixin
@@ -670,7 +668,7 @@ export const ONHIDE: string
670
668
  export const ONRESIZE: string
671
669
 
672
670
  declare global {
673
- const defineProps: (<T>(props: T) => Readonly<GetPropsType<T>>) & (<T>() => Readonly<T>)
671
+ const defineProps: (<T extends Properties = {}>(props: T) => Readonly<GetPropsType<T>>) & (<T>() => Readonly<T>)
674
672
  const defineOptions: <D extends Data = {}, P extends Properties = {}, C = {}, M extends Methods = {}, Mi extends Array<any> = [], S extends AnyObject = {}, O extends AnyObject = {}> (opt: ThisTypedComponentOpt<D, P, C, M, Mi, S, O>) => void
675
673
  const defineExpose: <E extends AnyObject = AnyObject>(exposed?: E) => void
676
674
  const useContext: () => Context
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@mpxjs/core",
3
- "version": "2.8.40-test",
3
+ "version": "2.8.40-test.2",
4
4
  "description": "mpx runtime core",
5
5
  "keywords": [
6
6
  "miniprogram",
7
7
  "mpx"
8
8
  ],
9
9
  "author": "donghongping",
10
- "license": "Apache",
10
+ "license": "Apache-2.0",
11
11
  "module": "src/index.js",
12
12
  "types": "@types/index.d.ts",
13
13
  "directories": {
@@ -19,15 +19,15 @@
19
19
  ],
20
20
  "main": "src/index.js",
21
21
  "dependencies": {
22
- "@mpxjs/utils": "^2.8.40-test",
22
+ "@mpxjs/utils": "^2.8.40-test.2",
23
23
  "lodash": "^4.1.1",
24
24
  "miniprogram-api-typings": "^3.10.0"
25
25
  },
26
26
  "peerDependencies": {
27
- "@mpxjs/api-proxy": "^2.7.44",
28
- "@mpxjs/store": "^2.8.0",
27
+ "@mpxjs/api-proxy": "^2.9.0",
28
+ "@mpxjs/store": "^2.9.0",
29
29
  "vue": "^2.7.10",
30
- "vue-demi": "^0.13.11",
30
+ "vue-demi": "^0.14.6",
31
31
  "vue-i18n": "^8.27.2",
32
32
  "vue-i18n-bridge": "^9.2.2"
33
33
  },
@@ -47,5 +47,5 @@
47
47
  "url": "https://github.com/didi/mpx/issues"
48
48
  },
49
49
  "sideEffects": false,
50
- "gitHead": "8524f9b69ebcfb0667ebff2608cf6f675f14f141"
50
+ "gitHead": "7b1911025a2eb47eddc046775f17b6f1405fdd54"
51
51
  }
@@ -10,6 +10,7 @@ export const ONLOAD = '__onLoad__'
10
10
  export const ONSHOW = '__onShow__'
11
11
  export const ONHIDE = '__onHide__'
12
12
  export const ONRESIZE = '__onResize__'
13
+ export const SERVERPREFETCH = '__serverPrefetch__'
13
14
 
14
15
  export const INNER_LIFECYCLES = [
15
16
  BEFORECREATE,
@@ -19,6 +20,7 @@ export const INNER_LIFECYCLES = [
19
20
  BEFOREUPDATE,
20
21
  UPDATED,
21
22
  BEFOREUNMOUNT,
23
+ SERVERPREFETCH,
22
24
  UNMOUNTED,
23
25
  ONLOAD,
24
26
  ONSHOW,
@@ -314,17 +314,19 @@ export function mergeToArray (parent, child, key) {
314
314
  function composeHooks (target, includes) {
315
315
  Object.keys(target).forEach(key => {
316
316
  if (!includes || includes[key]) {
317
- const hooksArr = target[key]
318
- hooksArr && (target[key] = function (...args) {
319
- let result
320
- for (let i = 0; i < hooksArr.length; i++) {
321
- if (typeof hooksArr[i] === 'function') {
322
- const data = hooksArr[i].apply(this, args)
323
- data !== undefined && (result = data)
317
+ const hooks = target[key]
318
+ if (Array.isArray(hooks)) {
319
+ target[key] = function (...args) {
320
+ let result
321
+ for (let i = 0; i < hooks.length; i++) {
322
+ if (typeof hooks[i] === 'function') {
323
+ const data = hooks[i].apply(this, args)
324
+ data !== undefined && (result = data)
325
+ }
324
326
  }
327
+ return result
325
328
  }
326
- return result
327
- })
329
+ }
328
330
  }
329
331
  })
330
332
  }
@@ -352,7 +354,7 @@ function transformHOOKS (options) {
352
354
  const componentHooksMap = makeMap(convertRule.lifecycle.component)
353
355
  for (const key in options) {
354
356
  // 使用Component创建page实例,页面专属生命周期&自定义方法需写在methods内部
355
- if (typeof options[key] === 'function' && key !== 'dataFn' && key !== 'setup' && !componentHooksMap[key]) {
357
+ if (typeof options[key] === 'function' && key !== 'dataFn' && key !== 'setup' && key !== 'serverPrefetch' && !componentHooksMap[key]) {
356
358
  if (!options.methods) options.methods = {}
357
359
  options.methods[key] = options[key]
358
360
  delete options[key]
package/src/core/proxy.js CHANGED
@@ -37,6 +37,7 @@ import {
37
37
  BEFOREUPDATE,
38
38
  UPDATED,
39
39
  BEFOREUNMOUNT,
40
+ SERVERPREFETCH,
40
41
  UNMOUNTED,
41
42
  ONLOAD,
42
43
  ONSHOW,
@@ -659,6 +660,7 @@ export const onLoad = createHook(ONLOAD)
659
660
  export const onShow = createHook(ONSHOW)
660
661
  export const onHide = createHook(ONHIDE)
661
662
  export const onResize = createHook(ONRESIZE)
663
+ export const onServerPrefetch = createHook(SERVERPREFETCH)
662
664
  export const onPullDownRefresh = createHook('__onPullDownRefresh__')
663
665
  export const onReachBottom = createHook('__onReachBottom__')
664
666
  export const onShareAppMessage = createHook('__onShareAppMessage__')
package/src/index.js CHANGED
@@ -29,6 +29,7 @@ export {
29
29
  UPDATED,
30
30
  BEFOREUNMOUNT,
31
31
  UNMOUNTED,
32
+ SERVERPREFETCH,
32
33
  ONLOAD,
33
34
  ONSHOW,
34
35
  ONHIDE,
@@ -42,6 +43,7 @@ export {
42
43
  onUpdated,
43
44
  onBeforeUnmount,
44
45
  onUnmounted,
46
+ onServerPrefetch,
45
47
  onLoad,
46
48
  onShow,
47
49
  onHide,
@@ -41,6 +41,7 @@ export default function pageScrollMixin (mixinType) {
41
41
  return {
42
42
  mounted () {
43
43
  this.__lastScrollY = 0
44
+ this.__originalOverflow = document.body.style.overflow
44
45
  },
45
46
  activated () {
46
47
  if (!refreshMs()) {
@@ -72,19 +73,22 @@ export default function pageScrollMixin (mixinType) {
72
73
  }
73
74
  },
74
75
  deactivated () {
75
- if (ms) {
76
+ if (ms) { // 保存滚动位置, 用于 keep-alive
76
77
  this.__lastScrollY = getScrollTop()
77
- ms.destroy()
78
- hideLoading(this)
79
78
  }
79
+ this.__uninstallMpxScroll()
80
80
  },
81
81
  beforeDestroy () {
82
- if (ms) {
83
- ms.destroy()
84
- hideLoading(this)
85
- }
82
+ this.__uninstallMpxScroll()
86
83
  },
87
84
  methods: {
85
+ __uninstallMpxScroll () {
86
+ if (ms) {
87
+ ms.destroy()
88
+ hideLoading(this)
89
+ document.body.style.overflow = this.__originalOverflow // 恢复原有 overflow, 避免影响其他页面
90
+ }
91
+ },
88
92
  __mpxPullDownHandler (autoStop = false, isRefresh = false) {
89
93
  this.__pullingDown = true
90
94
  // 同微信保持一致
@@ -1,4 +1,5 @@
1
1
  import {
2
+ BEFORECREATE,
2
3
  CREATED,
3
4
  ONHIDE,
4
5
  ONSHOW,
@@ -47,6 +48,18 @@ if (isBrowser) {
47
48
  window.addEventListener('resize', onResize)
48
49
  }
49
50
 
51
+ function getParentPage (vm) {
52
+ let parent = vm.$parent
53
+ while (parent) {
54
+ if (parent.route) {
55
+ return parent
56
+ } else if (parent.$page) {
57
+ return parent.$page
58
+ }
59
+ parent = parent.$parent
60
+ }
61
+ }
62
+
50
63
  export default function pageStatusMixin (mixinType) {
51
64
  const mixin = {}
52
65
 
@@ -63,33 +76,44 @@ export default function pageStatusMixin (mixinType) {
63
76
  },
64
77
  created () {
65
78
  // onLoad应该在用户声明周期CREATED后再执行,故此处使用原生created声明周期来触发onLoad
66
- const query = (global.__mpxRouter && global.__mpxRouter.currentRoute && global.__mpxRouter.currentRoute.query) || {}
79
+ const query = this.$root.$options?.router?.currentRoute?.query || {}
67
80
  this.__mpxProxy.callHook(ONLOAD, [query])
68
81
  }
69
82
  })
70
83
  }
71
84
 
85
+ // 创建组件时记录当前所属page,用于驱动pageLifetimes和onShow/onHide钩子
86
+ if (mixinType === 'component') {
87
+ Object.assign(mixin, {
88
+ [BEFORECREATE] () {
89
+ this.$page = getParentPage(this)
90
+ }
91
+ })
92
+ }
93
+
72
94
  Object.assign(mixin, {
73
95
  [CREATED] () {
74
- const pageInstance = mixinType === 'page' ? this : getCurrentPageInstance()
75
- if (pageInstance) {
76
- this.$watch(() => pageInstance.mpxPageStatus, status => {
77
- if (!status) return
78
- if (status === 'show') this.__mpxProxy.callHook(ONSHOW)
79
- if (status === 'hide') this.__mpxProxy.callHook(ONHIDE)
80
- const pageLifetimes = this.__mpxProxy.options.pageLifetimes
81
- if (pageLifetimes) {
82
- if (/^resize/.test(status) && isFunction(pageLifetimes.resize)) {
83
- // resize
84
- pageLifetimes.resize.call(this, systemInfo)
85
- } else if (isFunction(pageLifetimes[status])) {
86
- // show & hide
87
- pageLifetimes[status].call(this)
96
+ if (isBrowser) {
97
+ const pageInstance = mixinType === 'page' ? this : this.$page
98
+ if (pageInstance) {
99
+ this.$watch(() => pageInstance.mpxPageStatus, status => {
100
+ if (!status) return
101
+ if (status === 'show') this.__mpxProxy.callHook(ONSHOW)
102
+ if (status === 'hide') this.__mpxProxy.callHook(ONHIDE)
103
+ const pageLifetimes = this.__mpxProxy.options.pageLifetimes
104
+ if (pageLifetimes) {
105
+ if (/^resize/.test(status) && isFunction(pageLifetimes.resize)) {
106
+ // resize
107
+ pageLifetimes.resize.call(this, systemInfo)
108
+ } else if (isFunction(pageLifetimes[status])) {
109
+ // show & hide
110
+ pageLifetimes[status].call(this)
111
+ }
88
112
  }
89
- }
90
- }, {
91
- sync: true
92
- })
113
+ }, {
114
+ sync: true
115
+ })
116
+ }
93
117
  }
94
118
  }
95
119
  })
@@ -35,7 +35,7 @@ export default function proxyEventMixin () {
35
35
  let fallbackType = ''
36
36
  if (type === 'begin' || type === 'end') {
37
37
  // 地图的 regionchange 事件会派发 e.type 为 begin 和 end 的事件
38
- fallbackType = 'regionchange'
38
+ fallbackType = __mpx_mode__ === 'ali' ? 'regionChange' : 'regionchange'
39
39
  } else if (/-([a-z])/.test(type)) {
40
40
  fallbackType = dash2hump(type)
41
41
  } else if (__mpx_mode__ === 'ali') {
@@ -1,11 +1,12 @@
1
1
  import transferOptions from '../core/transferOptions'
2
2
  import mergeOptions from '../core/mergeOptions'
3
3
  import builtInKeysMap from './patch/builtInKeysMap'
4
- import { makeMap, spreadProp } from '@mpxjs/utils'
4
+ import { makeMap, spreadProp, isBrowser } from '@mpxjs/utils'
5
+ import { mergeLifecycle } from '../convertor/mergeLifecycle'
5
6
  import * as webLifecycle from '../platform/patch/web/lifecycle'
6
7
  import Mpx from '../index'
7
8
 
8
- const webAppHooksMap = makeMap(webLifecycle.LIFECYCLE.APP_HOOKS)
9
+ const webAppHooksMap = makeMap(mergeLifecycle(webLifecycle.LIFECYCLE).app)
9
10
 
10
11
  function filterOptions (options, appData) {
11
12
  const newOptions = {}
@@ -35,7 +36,7 @@ export default function createApp (option, config = {}) {
35
36
  created () {
36
37
  Object.assign(this, Mpx.prototype)
37
38
  Object.assign(this, appData)
38
- const current = (global.__mpxRouter && global.__mpxRouter.currentRoute) || {}
39
+ const current = this.$root.$options?.router?.currentRoute || {}
39
40
  const options = {
40
41
  path: current.path && current.path.replace(/^\//, ''),
41
42
  query: current.query,
@@ -49,19 +50,24 @@ export default function createApp (option, config = {}) {
49
50
  hide: [],
50
51
  error: []
51
52
  }
52
- if (this.$options.onShow) {
53
- this.$options.onShow.call(this, options)
54
- global.__mpxAppCbs.show.push(this.$options.onShow.bind(this))
55
- }
56
- if (this.$options.onHide) {
57
- global.__mpxAppCbs.hide.push(this.$options.onHide.bind(this))
58
- }
59
- if (this.$options.onError) {
60
- global.__mpxAppCbs.error.push(this.$options.onError.bind(this))
53
+ if (isBrowser) {
54
+ if (this.$options.onShow) {
55
+ this.$options.onShow.call(this, options)
56
+ global.__mpxAppCbs.show.push(this.$options.onShow.bind(this))
57
+ }
58
+ if (this.$options.onHide) {
59
+ global.__mpxAppCbs.hide.push(this.$options.onHide.bind(this))
60
+ }
61
+ if (this.$options.onError) {
62
+ global.__mpxAppCbs.error.push(this.$options.onError.bind(this))
63
+ }
61
64
  }
62
65
  }
63
66
  })
64
67
  } else {
68
+ if (option.onAppInit) {
69
+ option.onAppInit()
70
+ }
65
71
  builtInMixins.push({
66
72
  onLaunch () {
67
73
  Object.assign(this, Mpx.prototype)
@@ -77,6 +83,9 @@ export default function createApp (option, config = {}) {
77
83
  global.__mpxOptionsMap = global.__mpxOptionsMap || {}
78
84
  global.__mpxOptionsMap[global.currentModuleId] = defaultOptions
79
85
  global.getApp = function () {
86
+ if (!isBrowser) {
87
+ console.error('[Mpx runtime error]: Dangerous API! global.getApp method is running in non browser environments')
88
+ }
80
89
  return appData
81
90
  }
82
91
  } else {
@@ -3,7 +3,7 @@ import mergeOptions from '../../../core/mergeOptions'
3
3
  import { diffAndCloneA, hasOwn } from '@mpxjs/utils'
4
4
  import { getCurrentInstance as getCurrentVueInstance } from '../../export/index'
5
5
  import MpxProxy, { setCurrentInstance, unsetCurrentInstance } from '../../../core/proxy'
6
- import { BEFORECREATE, BEFOREUPDATE, UPDATED, BEFOREUNMOUNT, UNMOUNTED } from '../../../core/innerLifecycle'
6
+ import { BEFORECREATE, BEFOREUPDATE, UPDATED, BEFOREUNMOUNT, UNMOUNTED, SERVERPREFETCH } from '../../../core/innerLifecycle'
7
7
 
8
8
  function filterOptions (options) {
9
9
  const newOptions = {}
@@ -79,6 +79,9 @@ export function getDefaultOptions (type, { rawOptions = {} }) {
79
79
  },
80
80
  destroyed () {
81
81
  if (this.__mpxProxy) this.__mpxProxy.callHook(UNMOUNTED)
82
+ },
83
+ serverPrefetch () {
84
+ if (this.__mpxProxy) return this.__mpxProxy.callHook(SERVERPREFETCH)
82
85
  }
83
86
  }]
84
87
  // 为了在builtMixin中可以使用某些rootMixin实现的特性(如数据响应等),此处builtInMixin在rootMixin之后执行,但是当builtInMixin使用存在对应内建生命周期的目标平台声明周期写法时,可能会出现用户生命周期比builtInMixin中的生命周期先执行的情况,为了避免这种情况发生,builtInMixin应该尽可能使用内建生命周期来编写
@@ -9,7 +9,8 @@ const COMPONENT_HOOKS = [
9
9
  'deactivated',
10
10
  'beforeDestroy',
11
11
  'destroyed',
12
- 'errorCaptured'
12
+ 'errorCaptured',
13
+ 'serverPrefetch'
13
14
  ]
14
15
 
15
16
  const PAGE_HOOKS = [
@@ -38,7 +39,9 @@ const APP_HOOKS = [
38
39
  'onError',
39
40
  'onPageNotFound',
40
41
  'onUnhandledRejection',
41
- 'onThemeChange'
42
+ 'onThemeChange',
43
+ 'onSSRAppCreated',
44
+ 'onAppInit'
42
45
  ]
43
46
 
44
47
  export const LIFECYCLE = {
@@ -14,7 +14,8 @@ const APP_HOOKS = [
14
14
  'onError',
15
15
  'onPageNotFound',
16
16
  'onUnhandledRejection',
17
- 'onThemeChange'
17
+ 'onThemeChange',
18
+ 'onAppInit'
18
19
  ]
19
20
 
20
21
  const PAGE_HOOKS = [