@mpxjs/core 2.7.26 → 2.7.29

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
@@ -7,6 +7,8 @@
7
7
  /// <reference path="./mpx-store.d.ts" />
8
8
  /// <reference path="./global.d.ts" />
9
9
  /// <reference path="./node.d.ts" />
10
+
11
+ // @ts-ignore
10
12
  import VueI18n from 'vue-i18n'
11
13
 
12
14
  declare module 'vue-i18n' {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mpxjs/core",
3
- "version": "2.7.26",
3
+ "version": "2.7.29",
4
4
  "description": "mpx runtime core",
5
5
  "keywords": [
6
6
  "miniprogram",
@@ -41,5 +41,5 @@
41
41
  "url": "https://github.com/didi/mpx/issues"
42
42
  },
43
43
  "sideEffects": false,
44
- "gitHead": "bfad123d02a216278c122135148ba2a3977121d0"
44
+ "gitHead": "36f20ba8f22e0a1506679237d1e16df5a2e322b6"
45
45
  }
package/src/core/proxy.js CHANGED
@@ -41,13 +41,14 @@ export default class MPXProxy {
41
41
  this.uid = uid++
42
42
  this.name = options.name || ''
43
43
  this.options = options
44
- // initial -> created -> mounted -> destroyed
45
- this.state = 'initial'
44
+ // beforeCreate -> created -> mounted -> destroyed
45
+ this.state = BEFORECREATE
46
46
  this.lockTask = asyncLock()
47
47
  this.ignoreProxyMap = makeMap(EXPORT_MPX.config.ignoreProxyWhiteList)
48
48
  if (__mpx_mode__ !== 'web') {
49
49
  this._watchers = []
50
50
  this._namedWatchers = {}
51
+ this._computedWatchers = {}
51
52
  this._watcher = null
52
53
  this.localKeysMap = {} // 非props key
53
54
  this.renderData = {} // 渲染函数中收集的数据
@@ -62,13 +63,27 @@ export default class MPXProxy {
62
63
  this.initApi()
63
64
  this.callUserHook(BEFORECREATE)
64
65
  if (__mpx_mode__ !== 'web') {
65
- this.initState(this.options)
66
+ this.initState()
66
67
  }
67
68
  this.state = CREATED
68
69
  this.callUserHook(CREATED, params)
69
70
  if (__mpx_mode__ !== 'web') {
70
- // 强制走小程序原生渲染逻辑
71
- this.options.__nativeRender__ ? this.doRender() : this.initRender()
71
+ this.initRender()
72
+ }
73
+ }
74
+
75
+ reCreated (params) {
76
+ const options = this.options
77
+ this.state = BEFORECREATE
78
+ this.callUserHook(BEFORECREATE)
79
+ if (__mpx_mode__ !== 'web') {
80
+ this.initComputed(options.computed, true)
81
+ this.initWatch(options.watch)
82
+ }
83
+ this.state = CREATED
84
+ this.callUserHook(CREATED, params)
85
+ if (__mpx_mode__ !== 'web') {
86
+ this.initRender()
72
87
  }
73
88
  }
74
89
 
@@ -118,6 +133,10 @@ export default class MPXProxy {
118
133
  this.callUserHook(DESTROYED)
119
134
  }
120
135
 
136
+ isDestroyed () {
137
+ return this.state === DESTROYED
138
+ }
139
+
121
140
  initApi () {
122
141
  // 挂载扩展属性到实例上
123
142
  proxy(this.target, this.options.proto, Object.keys(this.options.proto), true, (key) => {
@@ -168,10 +187,15 @@ export default class MPXProxy {
168
187
  this.initWatch(options.watch)
169
188
  }
170
189
 
171
- initComputed (computedOpt) {
190
+ initComputed (computedOpt, reInit) {
172
191
  if (computedOpt) {
173
- this.collectLocalKeys(computedOpt)
174
- initComputed(this, this.data, computedOpt)
192
+ if (reInit) {
193
+ // target传递null以跳过computed挂载,仅重新初始化watchers
194
+ initComputed(this, null, computedOpt)
195
+ } else {
196
+ this.collectLocalKeys(computedOpt)
197
+ initComputed(this, this.data, computedOpt)
198
+ }
175
199
  }
176
200
  }
177
201
 
@@ -194,7 +218,9 @@ export default class MPXProxy {
194
218
  })
195
219
  Object.assign(this.data, dataFn.call(this.target))
196
220
  }
221
+ // 此时data中不包括props数据
197
222
  this.collectLocalKeys(this.data)
223
+ // 将props数据合并到data中
198
224
  Object.keys(initialData).forEach((key) => {
199
225
  if (!hasOwn(this.data, key)) {
200
226
  // 除了data函数返回的数据外深拷贝切断引用关系,避免后续watch由于小程序内部对data赋值重复触发watch
@@ -263,6 +289,7 @@ export default class MPXProxy {
263
289
  while (i--) {
264
290
  this._watchers[i].teardown()
265
291
  }
292
+ this._watchers.length = 0
266
293
  }
267
294
 
268
295
  render () {
@@ -414,9 +441,10 @@ export default class MPXProxy {
414
441
  }
415
442
 
416
443
  initRender () {
417
- let renderWatcher
444
+ if (this.options.__nativeRender__) return this.doRender()
445
+
418
446
  if (this.target.__injectedRender) {
419
- renderWatcher = new Watcher(this, () => {
447
+ this._watcher = new Watcher(this, () => {
420
448
  try {
421
449
  return this.target.__injectedRender()
422
450
  } catch (e) {
@@ -425,11 +453,10 @@ export default class MPXProxy {
425
453
  }
426
454
  }, noop, { pausable: true })
427
455
  } else {
428
- renderWatcher = new Watcher(this, () => {
456
+ this._watcher = new Watcher(this, () => {
429
457
  this.render()
430
458
  }, noop, { pausable: true })
431
459
  }
432
- this._watcher = renderWatcher
433
460
  }
434
461
 
435
462
  forceUpdate (data, options, callback) {
@@ -20,10 +20,12 @@ export function initComputed (vm, target, computed) {
20
20
  noop,
21
21
  { lazy: true }
22
22
  )
23
- if (!(key in target)) {
24
- defineComputed(vm, target, key, userDef)
25
- } else {
26
- error(`The computed key [${key}] is duplicated with data/props, please check.`, vm.options.mpxFileResource)
23
+ if (target) {
24
+ if (!(key in target)) {
25
+ defineComputed(vm, target, key, userDef)
26
+ } else {
27
+ error(`The computed key [${key}] is duplicated with data/props, please check.`, vm.options.mpxFileResource)
28
+ }
27
29
  }
28
30
  }
29
31
  }
@@ -84,23 +84,24 @@ function filterOptions (options, type) {
84
84
  }
85
85
 
86
86
  function initProxy (context, rawOptions, currentInject, params) {
87
- // 提供代理对象需要的api
88
- transformApiForProxy(context, currentInject)
89
- // 缓存options
90
- context.$rawOptions = rawOptions
91
- // 创建proxy对象
92
- const mpxProxy = new MPXProxy(rawOptions, context)
93
- context.__mpxProxy = mpxProxy
94
- context.__mpxProxy.created(params)
87
+ if (!context.__mpxProxy) {
88
+ // 提供代理对象需要的api
89
+ transformApiForProxy(context, currentInject)
90
+ // 缓存options
91
+ context.$rawOptions = rawOptions
92
+ // 创建proxy对象
93
+ context.__mpxProxy = new MPXProxy(rawOptions, context)
94
+ context.__mpxProxy.created(params)
95
+ } else if (context.__mpxProxy.isDestroyed()) {
96
+ context.__mpxProxy.reCreated(params)
97
+ }
95
98
  }
96
99
 
97
100
  export function getDefaultOptions (type, { rawOptions = {}, currentInject }) {
98
101
  const hookNames = type === 'component' ? ['onInit', 'didMount', 'didUnmount'] : ['onLoad', 'onReady', 'onUnload']
99
102
  const rootMixins = [{
100
103
  [hookNames[0]] (...params) {
101
- if (!this.__mpxProxy) {
102
- initProxy(this, rawOptions, currentInject, params)
103
- }
104
+ initProxy(this, rawOptions, currentInject, params)
104
105
  },
105
106
  deriveDataFromProps (nextProps) {
106
107
  if (this.__mpxProxy && this.__mpxProxy.isMounted() && nextProps && nextProps !== this.props) {
@@ -130,6 +131,7 @@ export function getDefaultOptions (type, { rawOptions = {}, currentInject }) {
130
131
  },
131
132
  didUpdate () {
132
133
  if (this.__mpxProxy) {
134
+ // todo: lockTask必要性待验证,属性更新触发自身setData时,updated执行与wx对齐,updated触发机制也考虑与wx对齐(props update && setData callback)
133
135
  this.__mpxProxy.lockTask(() => {
134
136
  this.__mpxProxy.updated()
135
137
  })
@@ -143,7 +145,7 @@ export function getDefaultOptions (type, { rawOptions = {}, currentInject }) {
143
145
  }
144
146
  },
145
147
  [hookNames[2]] () {
146
- this.__mpxProxy && this.__mpxProxy.destroyed()
148
+ if (this.__mpxProxy) this.__mpxProxy.destroyed()
147
149
  }
148
150
  }]
149
151
  rawOptions.mixins = rawOptions.mixins ? rootMixins.concat(rawOptions.mixins) : rootMixins
@@ -10,24 +10,20 @@ export function getDefaultOptions (type, { rawOptions = {}, currentInject }) {
10
10
 
11
11
  const rootMixin = {
12
12
  [hookNames[0]] (...params) {
13
- if (!this.__mpxProxy) {
14
- initProxy(this, rawOptions, currentInject, params)
15
- }
13
+ initProxy(this, rawOptions, currentInject, params)
16
14
  },
17
15
  [hookNames[1]] () {
18
- this.__mpxProxy && this.__mpxProxy.mounted()
16
+ if (this.__mpxProxy) this.__mpxProxy.mounted()
19
17
  },
20
18
  [hookNames[2]] () {
21
- this.__mpxProxy && this.__mpxProxy.destroyed()
19
+ if (this.__mpxProxy) this.__mpxProxy.destroyed()
22
20
  }
23
21
  }
24
22
 
25
23
  // 如构造页面,优先使用onInit进行初始化
26
24
  if (type === 'page') {
27
25
  rootMixin.onInit = function (...params) {
28
- if (!this.__mpxProxy) {
29
- initProxy(this, rawOptions, currentInject, params)
30
- }
26
+ initProxy(this, rawOptions, currentInject, params)
31
27
  }
32
28
  }
33
29
 
@@ -24,31 +24,33 @@ function filterOptions (options) {
24
24
  }
25
25
 
26
26
  function initProxy (context, rawOptions, params) {
27
- // 缓存options
28
- context.$rawOptions = rawOptions
29
- // 创建proxy对象
30
- const mpxProxy = new MPXProxy(rawOptions, context)
31
- context.__mpxProxy = mpxProxy
32
- context.__mpxProxy.created(params)
27
+ if (!context.__mpxProxy) {
28
+ // 缓存options
29
+ context.$rawOptions = rawOptions
30
+ // 创建proxy对象
31
+ context.__mpxProxy = new MPXProxy(rawOptions, context)
32
+ context.__mpxProxy.created(params)
33
+ } else if (context.__mpxProxy.isDestroyed()) {
34
+ context.__mpxProxy.reCreated(params)
35
+ }
33
36
  }
34
37
 
35
38
  export function getDefaultOptions (type, { rawOptions = {} }) {
36
39
  const rootMixins = [{
37
40
  created () {
38
- if (!this.__mpxProxy) {
39
- const query = (global.__mpxRouter && global.__mpxRouter.currentRoute && global.__mpxRouter.currentRoute.query) || {}
40
- initProxy(this, rawOptions, [query])
41
- this.onLoad && this.onLoad(query)
42
- }
41
+ const query = (global.__mpxRouter && global.__mpxRouter.currentRoute && global.__mpxRouter.currentRoute.query) || {}
42
+ initProxy(this, rawOptions, [query])
43
+ // web中单独触发onLoad
44
+ this.onLoad && this.onLoad(query)
43
45
  },
44
46
  mounted () {
45
- this.__mpxProxy && this.__mpxProxy.mounted()
47
+ if (this.__mpxProxy) this.__mpxProxy.mounted()
46
48
  },
47
49
  updated () {
48
- this.__mpxProxy && this.__mpxProxy.updated()
50
+ if (this.__mpxProxy) this.__mpxProxy.updated()
49
51
  },
50
52
  destroyed () {
51
- this.__mpxProxy && this.__mpxProxy.destroyed()
53
+ if (this.__mpxProxy) this.__mpxProxy.destroyed()
52
54
  }
53
55
  }]
54
56
  // 为了在builtMixin中可以使用某些rootMixin实现的特性(如数据响应等),此处builtInMixin在rootMixin之后执行,但是当builtInMixin使用存在对应内建生命周期的目标平台声明周期写法时,可能会出现用户生命周期比builtInMixin中的生命周期先执行的情况,为了避免这种情况发生,builtInMixin应该尽可能使用内建生命周期来编写
@@ -117,14 +117,17 @@ export function filterOptions (options) {
117
117
  }
118
118
 
119
119
  export function initProxy (context, rawOptions, currentInject, params) {
120
- // 提供代理对象需要的api
121
- transformApiForProxy(context, currentInject)
122
- // 缓存options
123
- context.$rawOptions = rawOptions
124
- // 创建proxy对象
125
- const mpxProxy = new MPXProxy(rawOptions, context)
126
- context.__mpxProxy = mpxProxy
127
- context.__mpxProxy.created(params)
120
+ if (!context.__mpxProxy) {
121
+ // 提供代理对象需要的api
122
+ transformApiForProxy(context, currentInject)
123
+ // 缓存options
124
+ context.$rawOptions = rawOptions
125
+ // 创建proxy对象
126
+ context.__mpxProxy = new MPXProxy(rawOptions, context)
127
+ context.__mpxProxy.created(params)
128
+ } else if (context.__mpxProxy.isDestroyed()) {
129
+ context.__mpxProxy.reCreated(params)
130
+ }
128
131
  }
129
132
 
130
133
  export function getDefaultOptions (type, { rawOptions = {}, currentInject }) {
@@ -135,15 +138,13 @@ export function getDefaultOptions (type, { rawOptions = {}, currentInject }) {
135
138
  }
136
139
  const rootMixins = [{
137
140
  [hookNames[0]] (...params) {
138
- if (!this.__mpxProxy) {
139
- initProxy(this, rawOptions, currentInject, params)
140
- }
141
+ initProxy(this, rawOptions, currentInject, params)
141
142
  },
142
143
  [hookNames[1]] () {
143
- this.__mpxProxy && this.__mpxProxy.mounted()
144
+ if (this.__mpxProxy) this.__mpxProxy.mounted()
144
145
  },
145
146
  [hookNames[2]] () {
146
- this.__mpxProxy && this.__mpxProxy.destroyed()
147
+ if (this.__mpxProxy) this.__mpxProxy.destroyed()
147
148
  }
148
149
  }]
149
150
  rawOptions.mixins = rawOptions.mixins ? rootMixins.concat(rawOptions.mixins) : rootMixins