@mpxjs/core 2.10.11 → 2.10.13

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
@@ -8,7 +8,7 @@
8
8
  /// <reference path="./node.d.ts" />
9
9
 
10
10
  import type { GetComputedType } from '@mpxjs/store'
11
-
11
+ import type { ScaledSize } from 'react-native'
12
12
  export * from '@mpxjs/store'
13
13
 
14
14
  // utils
@@ -122,6 +122,10 @@ interface Context {
122
122
  createIntersectionObserver: WechatMiniprogram.Component.InstanceMethods<Record<string, any>>['createIntersectionObserver'],
123
123
  getPageId: WechatMiniprogram.Component.InstanceMethods<Record<string, any>>['getPageId']
124
124
  }
125
+ type ExtendedComponentOptions = {
126
+ disconnectOnUnmounted?: boolean
127
+ shallowReactivePattern?: RegExp
128
+ } & WechatMiniprogram.Component.ComponentOptions
125
129
 
126
130
  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> {
127
131
  data?: D
@@ -130,6 +134,7 @@ interface ComponentOpt<D extends Data, P extends Properties, C, M extends Method
130
134
  methods?: M
131
135
  mixins?: Mi
132
136
  watch?: WatchField
137
+ options?: ExtendedComponentOptions
133
138
  setup?: (props: GetPropsType<P & UnboxMixinsField<Mi, 'properties'>>, context: Context) => S
134
139
 
135
140
  pageShow?: () => void
@@ -140,8 +145,8 @@ interface ComponentOpt<D extends Data, P extends Properties, C, M extends Method
140
145
 
141
146
  provide?: Record<string, any> | (() => Record<string, any>)
142
147
  inject?:
143
- | { [key: string]: string | Symbol | { from?: string | Symbol; default?: any } }
144
- | Array<string>
148
+ | { [key: string]: string | Symbol | { from?: string | Symbol; default?: any } }
149
+ | Array<string>
145
150
 
146
151
  [index: string]: any
147
152
  }
@@ -260,15 +265,122 @@ export interface WebviewConfig {
260
265
  apiImplementations?: object
261
266
  }
262
267
 
268
+ /**
269
+ * 输出为 ReactNative 时使用的特殊配置,用于与容器进行功能桥接
270
+ */
263
271
  export interface RnConfig {
264
- onStateChange?: (state: any) => void
265
- parseAppProps?: (props: any) => ({ initialRouteName?: string, initialParams?: any } | undefined | null | void)
266
272
  /**
267
- * 外层可能会异常设置此配置,因此加载监听函数内部
273
+ * 当导航状态发生变化时触发,例如页面跳转、返回等。
274
+ *
275
+ * @param state 当前的导航状态对象
276
+ */
277
+ onStateChange?: (state: Record<string, any>) => void;
278
+
279
+ /**
280
+ * 用于获取初始路由配置的函数。
281
+ *
282
+ * @param props ReactNative根组件接收到的参数
283
+ * @returns
284
+ * - `object`:包含 `initialRouteName` 和 `initialParams`
285
+ * - 或不返回,表示不设置初始路由
286
+ */
287
+ parseAppProps?: (
288
+ props: Record<string, any>
289
+ ) => { initialRouteName?: string; initialParams?: any } | void;
290
+
291
+ /**
292
+ * 页面栈长度为 1(即根页面)且用户尝试退出 App 时触发。
293
+ *
294
+ * @returns
295
+ * - `true`:允许退出应用
296
+ * - `false`:阻止退出应用
297
+ */
298
+ onAppBack?: () => boolean;
299
+
300
+ /**
301
+ * 是否禁用框架内部的 AppStateChange 监听。
302
+ */
303
+ disableAppStateListener?: boolean;
304
+
305
+ /**
306
+ * 控制首页回退按钮是否展示,并监听点击事件。
307
+ *
308
+ * 如果绑定该函数,则首页显示返回按钮,点击后调用该函数作为回调。
309
+ * 如需返回,请在函数内部手动调用 `back()`。
310
+ */
311
+ onStackTopBack?: () => void;
312
+
313
+ /**
314
+ * 容器实现的 open-type 能力集合。
315
+ */
316
+ openTypeHandler?: {
317
+ /**
318
+ * 在使用 button 组件并指定 `open-type="share"` 时触发分享。
319
+ *
320
+ * @param shareInfo 分享参数对象
321
+ * @param shareInfo.title 分享标题
322
+ * @param shareInfo.path 分享路径
323
+ * @param shareInfo.imageUrl 可选的分享图片
324
+ * @returns `void`
325
+ */
326
+ onShareAppMessage?: (shareInfo: {
327
+ title: string;
328
+ path: string;
329
+ imageUrl?: string;
330
+ }) => void;
331
+ };
332
+
333
+ /**
334
+ * 在使用 picker-view-column 时,触发短震动反馈。
335
+ */
336
+ pickerVibrate?: () => void;
337
+
338
+ /**
339
+ * 自定义屏幕尺寸信息,用于 mpx style 渲染等依赖尺寸的功能。
340
+ *
341
+ * @param dimensions 包含 window 和 screen 的尺寸信息
342
+ * @returns 返回修改后的尺寸对象,或 void 表示不修改
343
+ */
344
+ customDimensions?: <T extends { window: ScaledSize; screen: ScaledSize }>(
345
+ dimensions: T
346
+ ) => T | void;
347
+
348
+ /**
349
+ * 异步分包加载配置。
350
+ */
351
+ asyncChunk?: {
352
+ /**
353
+ * 加载超时时长配置,单位为毫秒。
354
+ */
355
+ timeout: number;
356
+
357
+ /**
358
+ * 异步分包页面加载超时或失败时,自定义兜底页面文件路径。
359
+ */
360
+ fallback: string;
361
+
362
+ /**
363
+ * 异步分包页面加载时,自定义 loading 页面文件路径。
364
+ */
365
+ loading: string;
366
+ };
367
+
368
+ /**
369
+ * 加载并执行异步分包的方法。
370
+ *
371
+ * @param params 分包下载参数
372
+ * @param params.url 资源地址
373
+ * @param params.package 分包名
374
+ * @returns Promise,表示加载完成
375
+ */
376
+ loadChunkAsync?: (params: { url: string; package: string }) => Promise<any>;
377
+
378
+ /**
379
+ * 下载多个异步分包的方法(不执行)。
380
+ *
381
+ * @param packages 分包名数组
268
382
  */
269
- disableAppStateListener?: boolean
270
- /** 进入页面是否控制回退按钮的展示以及监听回退按钮的点击 */
271
- onStackTopBack?: () => void
383
+ downloadChunkAsync?: (packages: Array<string>) => void;
272
384
  }
273
385
 
274
386
  interface MpxConfig {
@@ -598,11 +710,11 @@ export function set<T extends object> (target: T, key: string | number, value: a
598
710
  export function del<T extends object> (target: T, key: keyof T): void
599
711
 
600
712
  // provide & inject
601
- export declare function provide<T>(key: InjectionKey<T> | string | number, value: T): void;
602
- export declare function inject<T>(key: InjectionKey<T> | string): T | undefined;
603
- export declare function inject<T>(key: InjectionKey<T> | string, defaultValue: T, treatDefaultAsFactory?: false): T;
604
- export declare function inject<T>(key: InjectionKey<T> | string, defaultValue: T | (() => T), treatDefaultAsFactory: true): T;
605
- export declare interface InjectionKey<T> extends Symbol {}
713
+ export declare function provide<T> (key: InjectionKey<T> | string | number, value: T): void
714
+ export declare function inject<T> (key: InjectionKey<T> | string): T | undefined
715
+ export declare function inject<T> (key: InjectionKey<T> | string, defaultValue: T, treatDefaultAsFactory?: false): T
716
+ export declare function inject<T> (key: InjectionKey<T> | string, defaultValue: T | (() => T), treatDefaultAsFactory: true): T
717
+ export declare interface InjectionKey<T> extends Symbol { }
606
718
 
607
719
  // nextTick
608
720
  export function nextTick (fn: () => any): void
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/core",
3
- "version": "2.10.11",
3
+ "version": "2.10.13",
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.10.8",
22
+ "@mpxjs/utils": "^2.10.13",
23
23
  "lodash": "^4.1.1",
24
24
  "miniprogram-api-typings": "^3.10.0"
25
25
  },
@@ -109,5 +109,5 @@
109
109
  "url": "https://github.com/didi/mpx/issues"
110
110
  },
111
111
  "sideEffects": false,
112
- "gitHead": "4ea2a49ba7989edb3b0e292ed41e357d476d70fc"
112
+ "gitHead": "1b4a2d4765341ef6c6b74e501f72a0f856f247f9"
113
113
  }
package/src/core/proxy.js CHANGED
@@ -101,6 +101,7 @@ function preProcessRenderData (renderData) {
101
101
  })
102
102
  return processedRenderData
103
103
  }
104
+
104
105
  export default class MpxProxy {
105
106
  constructor (options, target, reCreated) {
106
107
  this.target = target
@@ -111,6 +112,7 @@ export default class MpxProxy {
111
112
  this.name = options.name || ''
112
113
  this.options = options
113
114
  this.shallowReactivePattern = this.options.options?.shallowReactivePattern
115
+ this.disconnectOnUnmounted = !!this.options.options?.disconnectOnUnmounted
114
116
  // beforeCreate -> created -> mounted -> unmounted
115
117
  this.state = BEFORECREATE
116
118
  this.ignoreProxyMap = makeMap(Mpx.config.ignoreProxyWhiteList)
@@ -257,6 +259,21 @@ export default class MpxProxy {
257
259
  observer.disconnect()
258
260
  })
259
261
  }
262
+ // 临时规避Reanimated worklet闭包捕获导致的内存泄漏问题
263
+ if (isReact && this.disconnectOnUnmounted) {
264
+ Object.keys(this.localKeysMap).forEach((key) => {
265
+ delete this.target[key]
266
+ })
267
+ Object.keys(this.props).forEach((key) => {
268
+ delete this.target[key]
269
+ })
270
+ this.scope = null
271
+ this.data = null
272
+ this.props = null
273
+ this.renderData = null
274
+ this.miniRenderData = null
275
+ this.forceUpdateData = null
276
+ }
260
277
  }
261
278
 
262
279
  isUnmounted () {
@@ -266,10 +283,10 @@ export default class MpxProxy {
266
283
  createProxyConflictHandler (owner) {
267
284
  return (key) => {
268
285
  if (this.ignoreProxyMap[key]) {
269
- !this.reCreated && error(`The ${owner} key [${key}] is a reserved keyword of miniprogram, please check and rename it.`, this.options.mpxFileResource)
286
+ error(`The ${owner} key [${key}] is a reserved keyword of miniprogram, please check and rename it.`, this.options.mpxFileResource)
270
287
  return false
271
288
  }
272
- !this.reCreated && error(`The ${owner} key [${key}] exist in the current instance already, please check and rename it.`, this.options.mpxFileResource)
289
+ if (!this.reCreated) error(`The ${owner} key [${key}] exist in the current instance already, please check and rename it.`, this.options.mpxFileResource)
273
290
  }
274
291
  }
275
292
 
@@ -467,10 +484,16 @@ export default class MpxProxy {
467
484
  return res
468
485
  }
469
486
 
470
- collectLocalKeys (data, filter = () => true) {
471
- Object.keys(data).filter((key) => filter(key, data[key])).forEach((key) => {
472
- this.localKeysMap[key] = true
473
- })
487
+ collectLocalKeys (data, filter) {
488
+ if (isFunction(filter)) {
489
+ Object.keys(data).filter((key) => filter(key, data[key])).forEach((key) => {
490
+ this.localKeysMap[key] = true
491
+ })
492
+ } else {
493
+ Object.keys(data).forEach((key) => {
494
+ this.localKeysMap[key] = true
495
+ })
496
+ }
474
497
  }
475
498
 
476
499
  callHook (hookName, params, hooksOnly) {
@@ -20,7 +20,6 @@ function customDimensions (dimensions) {
20
20
  height = dimensions.screen.height
21
21
  }
22
22
 
23
- customDimensions(rawDimensions)
24
23
  Dimensions.addEventListener('change', customDimensions)
25
24
 
26
25
  function rpx (value) {
@@ -44,6 +43,7 @@ const unit = {
44
43
  const empty = {}
45
44
 
46
45
  function formatValue (value) {
46
+ if (width === undefined) customDimensions(rawDimensions)
47
47
  const matched = unitRegExp.exec(value)
48
48
  if (matched) {
49
49
  if (!matched[2] || matched[2] === 'px') {
@@ -18,7 +18,6 @@ export function init (Mpx) {
18
18
  Mpx.i18n = createI18n(global.i18n)
19
19
  }
20
20
  initGlobalErrorHandling()
21
- initGlobalLazyLoadHandling()
22
21
  }
23
22
 
24
23
  function initGlobalErrorHandling () {
@@ -65,13 +64,3 @@ function initGlobalErrorHandling () {
65
64
  require('promise/setimmediate/rejection-tracking').enable(rejectionTrackingOptions)
66
65
  }
67
66
  }
68
-
69
- function initGlobalLazyLoadHandling () {
70
- global.onLazyLoadError = function (error) {
71
- if (global.__mpxAppCbs?.lazyLoad?.length) {
72
- global.__mpxAppCbs.lazyLoad.forEach((cb) => {
73
- cb(error)
74
- })
75
- }
76
- }
77
- }
@@ -3,7 +3,7 @@ import * as ReactNative from 'react-native'
3
3
  import { ReactiveEffect } from '../../observer/effect'
4
4
  import { watch } from '../../observer/watch'
5
5
  import { del, reactive, set } from '../../observer/reactive'
6
- import { hasOwn, isFunction, noop, isObject, isArray, getByPath, collectDataset, hump2dash, dash2hump, callWithErrorHandling, wrapMethodsWithErrorHandling, error } from '@mpxjs/utils'
6
+ import { hasOwn, isFunction, noop, isObject, isArray, getByPath, collectDataset, hump2dash, dash2hump, callWithErrorHandling, wrapMethodsWithErrorHandling, error, setFocusedNavigation } from '@mpxjs/utils'
7
7
  import MpxProxy from '../../core/proxy'
8
8
  import { BEFOREUPDATE, ONLOAD, UPDATED, ONSHOW, ONHIDE, ONRESIZE, REACTHOOKSEXEC } from '../../core/innerLifecycle'
9
9
  import mergeOptions from '../../core/mergeOptions'
@@ -301,6 +301,7 @@ function createInstance ({ propsRef, type, rawOptions, currentInject, validProps
301
301
  instance.route = props.route.name
302
302
  global.__mpxPagesMap = global.__mpxPagesMap || {}
303
303
  global.__mpxPagesMap[props.route.key] = [instance, props.navigation]
304
+ setFocusedNavigation(props.navigation)
304
305
  // App onLaunch 在 Page created 之前执行
305
306
  if (!global.__mpxAppHotLaunched && global.__mpxAppOnLaunch) {
306
307
  global.__mpxAppOnLaunch(props.navigation)