@mpxjs/core 2.9.70 → 2.9.71

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/core",
3
- "version": "2.9.70",
3
+ "version": "2.9.71",
4
4
  "description": "mpx runtime core",
5
5
  "keywords": [
6
6
  "miniprogram",
@@ -109,5 +109,5 @@
109
109
  "url": "https://github.com/didi/mpx/issues"
110
110
  },
111
111
  "sideEffects": false,
112
- "gitHead": "ad8f04de95865ffc2b50b8c0a7f87b5952fb8647"
112
+ "gitHead": "38446f301a17e78dbe3ca7dacd771c79eb7a8ede"
113
113
  }
@@ -122,9 +122,10 @@ function extractObservers (options) {
122
122
  Object.keys(props).forEach(key => {
123
123
  const prop = props[key]
124
124
  if (prop && prop.observer) {
125
+ let callback = prop.observer
126
+ delete prop.observer
125
127
  mergeWatch(key, {
126
128
  handler (...rest) {
127
- let callback = prop.observer
128
129
  if (typeof callback === 'string') {
129
130
  callback = this[callback]
130
131
  }
@@ -168,11 +169,7 @@ function extractObservers (options) {
168
169
  cb = this[cb]
169
170
  }
170
171
  if (typeof cb === 'function') {
171
- if (keyPathArr.length < 2) {
172
- val = [val]
173
- old = [old]
174
- }
175
- cb.call(this, ...val, ...old)
172
+ Array.isArray(val) ? cb.call(this, ...val) : cb.call(this, val)
176
173
  }
177
174
  },
178
175
  deep,
package/src/core/proxy.js CHANGED
@@ -1,4 +1,4 @@
1
- import { reactive } from '../observer/reactive'
1
+ import { reactive, defineReactive } from '../observer/reactive'
2
2
  import { ReactiveEffect, pauseTracking, resetTracking } from '../observer/effect'
3
3
  import { effectScope } from '../platform/export/index'
4
4
  import { watch } from '../observer/watch'
@@ -111,7 +111,7 @@ export default class MpxProxy {
111
111
  this.uid = uid++
112
112
  this.name = options.name || ''
113
113
  this.options = options
114
- this.ignoreReactivePattern = this.options.options?.ignoreReactivePattern
114
+ this.shallowReactivePattern = this.options.options?.shallowReactivePattern
115
115
  // beforeCreate -> created -> mounted -> unmounted
116
116
  this.state = BEFORECREATE
117
117
  this.ignoreProxyMap = makeMap(Mpx.config.ignoreProxyWhiteList)
@@ -145,10 +145,12 @@ export default class MpxProxy {
145
145
  this.initApi()
146
146
  }
147
147
 
148
- processIgnoreReactive (obj) {
149
- if (this.ignoreReactivePattern && isObject(obj)) {
148
+ processShallowReactive (obj) {
149
+ if (this.shallowReactivePattern && isObject(obj)) {
150
150
  Object.keys(obj).forEach((key) => {
151
- if (this.ignoreReactivePattern.test(key)) {
151
+ if (this.shallowReactivePattern.test(key)) {
152
+ // 命中shallowReactivePattern的属性将其设置为 shallowReactive
153
+ defineReactive(obj, key, obj[key], true)
152
154
  Object.defineProperty(obj, key, {
153
155
  enumerable: true,
154
156
  // set configurable to false to skip defineReactive
@@ -290,10 +292,10 @@ export default class MpxProxy {
290
292
  if (isReact) {
291
293
  // react模式下props内部对象透传无需深clone,依赖对象深层的数据响应触发子组件更新
292
294
  this.props = this.target.__getProps()
293
- reactive(this.processIgnoreReactive(this.props))
295
+ reactive(this.processShallowReactive(this.props))
294
296
  } else {
295
297
  this.props = diffAndCloneA(this.target.__getProps(this.options)).clone
296
- reactive(this.processIgnoreReactive(this.props))
298
+ reactive(this.processShallowReactive(this.props))
297
299
  }
298
300
  proxy(this.target, this.props, undefined, false, this.createProxyConflictHandler('props'))
299
301
  }
@@ -333,7 +335,7 @@ export default class MpxProxy {
333
335
  if (isFunction(dataFn)) {
334
336
  Object.assign(this.data, callWithErrorHandling(dataFn.bind(this.target), this, 'data function'))
335
337
  }
336
- reactive(this.processIgnoreReactive(this.data))
338
+ reactive(this.processShallowReactive(this.data))
337
339
  proxy(this.target, this.data, undefined, false, this.createProxyConflictHandler('data'))
338
340
  this.collectLocalKeys(this.data)
339
341
  }
@@ -514,7 +516,7 @@ export default class MpxProxy {
514
516
  if (hasOwn(renderData, key)) {
515
517
  const data = renderData[key]
516
518
  const firstKey = getFirstKey(key)
517
- if (!this.localKeysMap[firstKey] || (this.ignoreReactivePattern && this.ignoreReactivePattern.test(firstKey))) {
519
+ if (!this.localKeysMap[firstKey]) {
518
520
  continue
519
521
  }
520
522
  // 外部clone,用于只需要clone的场景
@@ -1,4 +1,5 @@
1
- import { setByPath } from '@mpxjs/utils'
1
+ import { setByPath, error, parseDataset } from '@mpxjs/utils'
2
+ import Mpx from '../../index'
2
3
 
3
4
  export default function proxyEventMixin () {
4
5
  return {
@@ -19,11 +20,58 @@ export default function proxyEventMixin () {
19
20
  const value = filterMethod ? (innerFilter[filterMethod] ? innerFilter[filterMethod](originValue) : typeof this[filterMethod] === 'function' && this[filterMethod]) : originValue
20
21
  setByPath(this, expr, value)
21
22
  },
22
- __invokeHandler (eventName, $event) {
23
- const handler = this[eventName]
24
- if (handler && typeof handler === 'function') {
25
- handler.call(this, $event)
23
+ __invoke (rawEvent, eventConfig = []) {
24
+ if (typeof Mpx.config.proxyEventHandler === 'function') {
25
+ try {
26
+ Mpx.config.proxyEventHandler(rawEvent)
27
+ } catch (e) {}
26
28
  }
29
+ const location = this.__mpxProxy.options.mpxFileResource
30
+
31
+ if (rawEvent.target && !rawEvent.target._datasetProcessed) {
32
+ const originalDataset = rawEvent.target.dataset
33
+ Object.defineProperty(rawEvent.target, 'dataset', {
34
+ get: () => parseDataset(originalDataset),
35
+ configurable: true,
36
+ enumerable: true
37
+ })
38
+ rawEvent.target._datasetProcessed = true
39
+ }
40
+ if (rawEvent.currentTarget && !rawEvent.currentTarget._datasetProcessed) {
41
+ const originalDataset = rawEvent.currentTarget.dataset
42
+ Object.defineProperty(rawEvent.currentTarget, 'dataset', {
43
+ get: () => parseDataset(originalDataset),
44
+ configurable: true,
45
+ enumerable: true
46
+ })
47
+ rawEvent.currentTarget._datasetProcessed = true
48
+ }
49
+
50
+ let returnedValue
51
+ eventConfig.forEach((item) => {
52
+ const callbackName = item[0]
53
+ if (callbackName) {
54
+ const params =
55
+ item.length > 1
56
+ ? item.slice(1).map((item) => {
57
+ if (item === '__mpx_event__') {
58
+ return rawEvent
59
+ } else {
60
+ return item
61
+ }
62
+ })
63
+ : [rawEvent]
64
+ if (typeof this[callbackName] === 'function') {
65
+ returnedValue = this[callbackName].apply(this, params)
66
+ } else {
67
+ error(
68
+ `Instance property [${callbackName}] is not function, please check.`,
69
+ location
70
+ )
71
+ }
72
+ }
73
+ })
74
+ return returnedValue
27
75
  }
28
76
  }
29
77
  }
@@ -1,13 +1,12 @@
1
1
  import transferOptions from '../core/transferOptions'
2
2
  import builtInKeysMap from './patch/builtInKeysMap'
3
- import { makeMap, spreadProp, getFocusedNavigation, hasOwn, extend } from '@mpxjs/utils'
3
+ import { makeMap, spreadProp, getFocusedNavigation, hasOwn } from '@mpxjs/utils'
4
4
  import { mergeLifecycle } from '../convertor/mergeLifecycle'
5
5
  import { LIFECYCLE } from '../platform/patch/lifecycle/index'
6
6
  import Mpx from '../index'
7
7
  import { createElement, memo, useRef, useEffect } from 'react'
8
8
  import * as ReactNative from 'react-native'
9
9
  import { Image } from 'react-native'
10
- import { ref } from '../observer/ref'
11
10
 
12
11
  const appHooksMap = makeMap(mergeLifecycle(LIFECYCLE).app)
13
12
 
@@ -30,22 +29,27 @@ function filterOptions (options, appData) {
30
29
  return newOptions
31
30
  }
32
31
 
33
- function createAppInstance (appData) {
34
- return extend({}, Mpx.prototype, appData)
35
- }
36
-
37
- export default function createApp (option, config = {}) {
32
+ export default function createApp (options) {
38
33
  const appData = {}
39
34
 
40
35
  const { NavigationContainer, createStackNavigator, SafeAreaProvider } = global.__navigationHelper
41
36
  // app选项目前不需要进行转换
42
- const { rawOptions, currentInject } = transferOptions(option, 'app', false)
37
+ const { rawOptions, currentInject } = transferOptions(options, 'app', false)
43
38
  const defaultOptions = filterOptions(spreadProp(rawOptions, 'methods'), appData)
44
- defaultOptions.onAppInit && defaultOptions.onAppInit()
45
39
  // 在页面script执行前填充getApp()
46
40
  global.getApp = function () {
47
41
  return appData
48
42
  }
43
+
44
+ // 模拟小程序appInstance在热启动时不会重新创建的行为,在外部创建跟随js context的appInstance
45
+ const appInstance = Object.assign({}, appData, Mpx.prototype)
46
+
47
+ defaultOptions.onShow && global.__mpxAppCbs.show.push(defaultOptions.onShow.bind(appInstance))
48
+ defaultOptions.onHide && global.__mpxAppCbs.hide.push(defaultOptions.onHide.bind(appInstance))
49
+ defaultOptions.onError && global.__mpxAppCbs.error.push(defaultOptions.onError.bind(appInstance))
50
+ defaultOptions.onUnhandledRejection && global.__mpxAppCbs.rejection.push(defaultOptions.onUnhandledRejection.bind(appInstance))
51
+ defaultOptions.onAppInit && defaultOptions.onAppInit()
52
+
49
53
  const pages = currentInject.getPages() || {}
50
54
  const firstPage = currentInject.firstPage
51
55
  const Stack = createStackNavigator()
@@ -82,55 +86,50 @@ export default function createApp (option, config = {}) {
82
86
  }
83
87
 
84
88
  global.__mpxAppLaunched = false
85
-
86
- global.__mpxAppFocusedState = ref('show')
87
89
  global.__mpxOptionsMap[currentInject.moduleId] = memo((props) => {
88
- const instanceRef = useRef(null)
89
- if (!instanceRef.current) {
90
- instanceRef.current = createAppInstance(appData)
91
- }
92
- const instance = instanceRef.current
90
+ const firstRef = useRef(true)
93
91
  const initialRouteRef = useRef({
94
92
  initialRouteName: firstPage,
95
93
  initialParams: {}
96
94
  })
97
-
98
- if (!global.__mpxAppLaunched) {
95
+ if (firstRef.current) {
96
+ // 热启动情况下,app会被销毁重建,将__mpxAppHotLaunched重置保障路由等初始化逻辑正确执行
97
+ global.__mpxAppHotLaunched = false
98
+ // 热启动情况下重置__mpxPagesMap避免页面销毁函数未及时执行时错误地引用到之前的navigation
99
+ global.__mpxPagesMap = {}
100
+ firstRef.current = false
101
+ }
102
+ if (!global.__mpxAppHotLaunched) {
99
103
  const { initialRouteName, initialParams } = Mpx.config.rnConfig.parseAppProps?.(props) || {}
100
104
  initialRouteRef.current.initialRouteName = initialRouteName || initialRouteRef.current.initialRouteName
101
105
  initialRouteRef.current.initialParams = initialParams || initialRouteRef.current.initialParams
102
106
 
103
107
  global.__mpxAppOnLaunch = (navigation) => {
104
- global.__mpxAppLaunched = true
105
108
  const state = navigation.getState()
106
109
  Mpx.config.rnConfig.onStateChange?.(state)
107
110
  const current = state.routes[state.index]
108
- global.__mpxEnterOptions = {
111
+ const options = {
109
112
  path: current.name,
110
113
  query: current.params,
111
114
  scene: 0,
112
115
  shareTicket: '',
113
- referrerInfo: {}
116
+ referrerInfo: {},
117
+ isLaunch: true
118
+ }
119
+ global.__mpxEnterOptions = options
120
+ if (!global.__mpxAppLaunched) {
121
+ global.__mpxLaunchOptions = options
122
+ defaultOptions.onLaunch && defaultOptions.onLaunch.call(appInstance, options)
114
123
  }
115
- defaultOptions.onLaunch && defaultOptions.onLaunch.call(instance, global.__mpxEnterOptions)
116
- defaultOptions.onShow && defaultOptions.onShow.call(instance, global.__mpxEnterOptions)
124
+ global.__mpxAppCbs.show.forEach((cb) => {
125
+ cb(options)
126
+ })
127
+ global.__mpxAppLaunched = true
128
+ global.__mpxAppHotLaunched = true
117
129
  }
118
130
  }
119
131
 
120
132
  useEffect(() => {
121
- if (defaultOptions.onShow) {
122
- global.__mpxAppCbs.show.push(defaultOptions.onShow.bind(instance))
123
- }
124
- if (defaultOptions.onHide) {
125
- global.__mpxAppCbs.hide.push(defaultOptions.onHide.bind(instance))
126
- }
127
- if (defaultOptions.onError) {
128
- global.__mpxAppCbs.error.push(defaultOptions.onError.bind(instance))
129
- }
130
- if (defaultOptions.onUnhandledRejection) {
131
- global.__mpxAppCbs.rejection.push(defaultOptions.onUnhandledRejection.bind(instance))
132
- }
133
-
134
133
  const changeSubscription = ReactNative.AppState.addEventListener('change', (currentState) => {
135
134
  if (currentState === 'active') {
136
135
  let options = global.__mpxEnterOptions
@@ -24,19 +24,29 @@ function filterOptions (options, appData) {
24
24
  return newOptions
25
25
  }
26
26
 
27
- export default function createApp (option, config = {}) {
28
- // 在App中挂载mpx对象供周边工具访问,如e2e测试
27
+ export default function createApp (options, config = {}) {
28
+ const appData = {}
29
+ // app选项目前不需要进行转换
30
+ const { rawOptions, currentInject } = transferOptions(options, 'app', false)
29
31
  const builtInMixins = [{
32
+ // 在App中挂载mpx对象供周边工具访问,如e2e测试
30
33
  getMpx () {
31
34
  return Mpx
32
35
  }
33
36
  }]
34
- const appData = {}
35
37
  if (__mpx_mode__ === 'web') {
36
38
  builtInMixins.push({
39
+ beforeCreate () {
40
+ // for vue provide vm access
41
+ Object.assign(this, appData, Mpx.prototype)
42
+ if (isBrowser) {
43
+ rawOptions.onShow && global.__mpxAppCbs.show.push(rawOptions.onShow.bind(this))
44
+ rawOptions.onHide && global.__mpxAppCbs.hide.push(rawOptions.onHide.bind(this))
45
+ rawOptions.onError && global.__mpxAppCbs.error.push(rawOptions.onError.bind(this))
46
+ rawOptions.onUnhandledRejection && global.__mpxAppCbs.rejection.push(rawOptions.onUnhandledRejection.bind(this))
47
+ }
48
+ },
37
49
  created () {
38
- Object.assign(this, Mpx.prototype)
39
- Object.assign(this, appData)
40
50
  const current = this.$root.$options?.router?.currentRoute || {}
41
51
  const options = {
42
52
  path: current.path && current.path.replace(/^\//, ''),
@@ -45,48 +55,36 @@ export default function createApp (option, config = {}) {
45
55
  shareTicket: '',
46
56
  referrerInfo: {}
47
57
  }
58
+ // web不分冷启动和热启动
48
59
  global.__mpxEnterOptions = options
49
- this.$options.onLaunch && this.$options.onLaunch.call(this, options)
50
- if (isBrowser) {
51
- if (this.$options.onShow) {
52
- this.$options.onShow.call(this, options)
53
- global.__mpxAppCbs.show.push(this.$options.onShow.bind(this))
54
- }
55
- if (this.$options.onHide) {
56
- global.__mpxAppCbs.hide.push(this.$options.onHide.bind(this))
57
- }
58
- if (this.$options.onError) {
59
- global.__mpxAppCbs.error.push(this.$options.onError.bind(this))
60
- }
61
- if (this.$options.onUnhandledRejection) {
62
- global.__mpxAppCbs.rejection.push(this.$options.onUnhandledRejection.bind(this))
63
- }
64
- }
60
+ global.__mpxLaunchOptions = options
61
+ rawOptions.onLaunch && rawOptions.onLaunch.call(this, options)
62
+ global.__mpxAppCbs.show.forEach((cb) => {
63
+ cb(options)
64
+ })
65
65
  }
66
66
  })
67
67
  } else {
68
68
  builtInMixins.push({
69
69
  onLaunch () {
70
70
  Object.assign(this, Mpx.prototype)
71
+ initAppProvides(rawOptions.provide, this)
71
72
  }
72
73
  })
73
74
  }
74
- // app选项目前不需要进行转换
75
- const { rawOptions, currentInject } = transferOptions(option, 'app', false)
76
75
  rawOptions.mixins = builtInMixins
77
76
  const defaultOptions = filterOptions(spreadProp(mergeOptions(rawOptions, 'app', false), 'methods'), appData)
78
77
 
79
78
  if (__mpx_mode__ === 'web') {
80
- global.__mpxOptionsMap = global.__mpxOptionsMap || {}
81
- global.__mpxOptionsMap[currentInject.moduleId] = defaultOptions
82
79
  global.getApp = function () {
83
80
  if (!isBrowser) {
84
81
  console.error('[Mpx runtime error]: Dangerous API! global.getApp method is running in non browser environments')
85
82
  }
86
83
  return appData
87
84
  }
85
+ global.__mpxOptionsMap = global.__mpxOptionsMap || {}
86
+ global.__mpxOptionsMap[currentInject.moduleId] = defaultOptions
88
87
  } else {
89
- initAppProvides(rawOptions)
90
88
  defaultOptions.onAppInit && defaultOptions.onAppInit()
91
89
  const ctor = config.customCtor || global.currentCtor || App
92
90
  ctor(defaultOptions)
@@ -11,57 +11,60 @@ function extendEvent (e, extendObj = {}) {
11
11
  })
12
12
  }
13
13
 
14
- function MpxEvent (layer) {
15
- this.targetElement = null
16
- this.touches = []
17
- this.touchStartX = 0
18
- this.touchStartY = 0
19
- this.startTimer = null
20
- this.needTap = true
21
- this.isTouchDevice = document && ('ontouchstart' in document.documentElement)
14
+ function createMpxEvent (layer) {
15
+ let startTimer = null
16
+ let needTap = true
17
+ let touchStartX = 0
18
+ let touchStartY = 0
19
+ let targetElement = null
20
+ const isTouchDevice = document && 'ontouchstart' in document.documentElement
22
21
 
23
- this.onTouchStart = (event) => {
22
+ const onTouchStart = (event) => {
24
23
  if (event.targetTouches?.length > 1) {
25
24
  return true
26
25
  }
27
- this.touches = event.targetTouches
28
- this.targetElement = event.target
29
- this.needTap = true
30
- this.startTimer = null
31
- this.touchStartX = this.touches[0].pageX
32
- this.touchStartY = this.touches[0].pageY
33
- this.startTimer = setTimeout(() => {
34
- this.needTap = false
35
- this.sendEvent(this.targetElement, 'longpress', event)
36
- this.sendEvent(this.targetElement, 'longtap', event)
26
+ const touches = event.targetTouches
27
+ targetElement = event.target
28
+ needTap = true
29
+ startTimer = null
30
+ touchStartX = touches[0].pageX
31
+ touchStartY = touches[0].pageY
32
+ startTimer = setTimeout(() => {
33
+ needTap = false
34
+ sendEvent(targetElement, 'longpress', event)
35
+ sendEvent(targetElement, 'longtap', event)
37
36
  }, 350)
38
37
  }
39
38
 
40
- this.onTouchMove = (event) => {
39
+ const onTouchMove = (event) => {
41
40
  const touch = event.changedTouches[0]
42
- if (Math.abs(touch.pageX - this.touchStartX) > 1 || Math.abs(touch.pageY - this.touchStartY) > 1) {
43
- this.needTap = false
44
- this.startTimer && clearTimeout(this.startTimer)
45
- this.startTimer = null
41
+ if (
42
+ Math.abs(touch.pageX - touchStartX) > 1 ||
43
+ Math.abs(touch.pageY - touchStartY) > 1
44
+ ) {
45
+ needTap = false
46
+ startTimer && clearTimeout(startTimer)
47
+ startTimer = null
46
48
  }
47
49
  }
48
50
 
49
- this.onTouchEnd = (event) => {
51
+ const onTouchEnd = (event) => {
50
52
  if (event.targetTouches?.length > 1) {
51
53
  return true
52
54
  }
53
- this.startTimer && clearTimeout(this.startTimer)
54
- this.startTimer = null
55
- if (this.needTap) {
56
- this.sendEvent(this.targetElement, 'tap', event)
55
+ startTimer && clearTimeout(startTimer)
56
+ startTimer = null
57
+ if (needTap) {
58
+ sendEvent(targetElement, 'tap', event)
57
59
  }
58
60
  }
59
61
 
60
- this.onClick = (event) => {
61
- this.targetElement = event.target
62
- this.sendEvent(this.targetElement, 'tap', event)
62
+ const onClick = (event) => {
63
+ targetElement = event.target
64
+ sendEvent(targetElement, 'tap', event)
63
65
  }
64
- this.sendEvent = (targetElement, type, event) => {
66
+
67
+ const sendEvent = (targetElement, type, event) => {
65
68
  const touchEvent = new CustomEvent(type, {
66
69
  bubbles: true,
67
70
  cancelable: true
@@ -72,7 +75,6 @@ function MpxEvent (layer) {
72
75
  changedTouches,
73
76
  touches: changedTouches,
74
77
  detail: {
75
- // pc端点击事件可能没有changedTouches,所以直接从 event中取
76
78
  x: changedTouches[0]?.pageX || event.pageX || 0,
77
79
  y: changedTouches[0]?.pageY || event.pageY || 0
78
80
  }
@@ -80,28 +82,23 @@ function MpxEvent (layer) {
80
82
  targetElement && targetElement.dispatchEvent(touchEvent)
81
83
  }
82
84
 
83
- this.addListener = () => {
84
- if (this.isTouchDevice) {
85
- layer.addEventListener('touchstart', this.onTouchStart, true)
86
- layer.addEventListener('touchmove', this.onTouchMove, true)
87
- layer.addEventListener('touchend', this.onTouchEnd, true)
88
- } else {
89
- layer.addEventListener('click', this.onClick, true)
90
- }
85
+ if (isTouchDevice) {
86
+ layer.addEventListener('touchstart', onTouchStart, true)
87
+ layer.addEventListener('touchmove', onTouchMove, true)
88
+ layer.addEventListener('touchend', onTouchEnd, true)
89
+ } else {
90
+ layer.addEventListener('click', onClick, true)
91
91
  }
92
- this.addListener()
93
92
  }
94
93
 
95
94
  export function initEvent () {
96
95
  if (isBrowser && !global.__mpxCreatedEvent) {
97
96
  global.__mpxCreatedEvent = true
98
97
  if (document.readyState === 'complete' || document.readyState === 'interactive') {
99
- // eslint-disable-next-line no-new
100
- new MpxEvent(document.body)
98
+ createMpxEvent(document.body)
101
99
  } else {
102
100
  document.addEventListener('DOMContentLoaded', function () {
103
- // eslint-disable-next-line no-new
104
- new MpxEvent(document.body)
101
+ createMpxEvent(document.body)
105
102
  }, false)
106
103
  }
107
104
  }
@@ -60,17 +60,23 @@ export default function install (Vue) {
60
60
  data: {
61
61
  get () {
62
62
  return Object.assign({}, this.$props, this.$data)
63
- }
63
+ },
64
+ enumerable: true,
65
+ configurable: true
64
66
  },
65
67
  dataset: {
66
68
  get () {
67
69
  return collectDataset(this.$attrs, true)
68
- }
70
+ },
71
+ enumerable: true,
72
+ configurable: true
69
73
  },
70
74
  id: {
71
75
  get () {
72
76
  return this.$attrs.id || ''
73
- }
77
+ },
78
+ enumerable: true,
79
+ configurable: true
74
80
  }
75
81
  })
76
82
 
@@ -11,11 +11,10 @@ const providesMap = {
11
11
  global.__mpxProvidesMap = providesMap
12
12
 
13
13
  /** @internal createApp() 初始化应用层 scope provide */
14
- export function initAppProvides (appOptions) {
15
- const provideOpt = appOptions.provide
14
+ export function initAppProvides (provideOpt, instance) {
16
15
  if (provideOpt) {
17
16
  const provided = isFunction(provideOpt)
18
- ? callWithErrorHandling(provideOpt.bind(appOptions), appOptions, 'createApp provide function')
17
+ ? callWithErrorHandling(provideOpt.bind(instance), instance, 'createApp provide function')
19
18
  : provideOpt
20
19
  if (isObject(provided)) {
21
20
  providesMap.__app = provided
@@ -365,14 +365,10 @@ function usePageStatus (navigation, pageId) {
365
365
  const blurSubscription = navigation.addListener('blur', () => {
366
366
  pageStatusMap[pageId] = 'hide'
367
367
  })
368
- const unWatchAppFocusedState = watch(global.__mpxAppFocusedState, (value) => {
369
- pageStatusMap[pageId] = value
370
- })
371
368
 
372
369
  return () => {
373
370
  focusSubscription()
374
371
  blurSubscription()
375
- unWatchAppFocusedState()
376
372
  del(pageStatusMap, pageId)
377
373
  }
378
374
  }, [navigation])
@@ -442,10 +438,17 @@ export function getDefaultOptions ({ type, rawOptions = {}, currentInject }) {
442
438
 
443
439
  useEffect(() => {
444
440
  if (type === 'page') {
445
- if (!global.__mpxAppLaunched && global.__mpxAppOnLaunch) {
441
+ if (!global.__mpxAppHotLaunched && global.__mpxAppOnLaunch) {
446
442
  global.__mpxAppOnLaunch(props.navigation)
447
443
  }
448
- proxy.callHook(ONLOAD, [props.route.params || {}])
444
+ const loadParams = {}
445
+ // 此处拿到的props.route.params内属性的value被进行过了一次decode, 不符合预期,此处额外进行一次encode来与微信对齐
446
+ if (isObject(props.route.params)) {
447
+ for (const key in props.route.params) {
448
+ loadParams[key] = encodeURIComponent(props.route.params[key])
449
+ }
450
+ }
451
+ proxy.callHook(ONLOAD, [loadParams])
449
452
  }
450
453
  proxy.mounted()
451
454
  return () => {
@@ -23,13 +23,11 @@ function transformProperties (properties) {
23
23
  } else {
24
24
  newFiled = Object.assign({}, rawFiled)
25
25
  }
26
- const rawObserver = rawFiled?.observer
27
26
  newFiled.observer = function (value, oldValue) {
28
27
  if (this.__mpxProxy) {
29
28
  this[key] = value
30
29
  this.__mpxProxy.propsUpdated()
31
30
  }
32
- rawObserver && rawObserver.call(this, value, oldValue)
33
31
  }
34
32
  newProps[key] = newFiled
35
33
  })