@mpxjs/core 2.8.32 → 2.9.0-beta.0
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 +2 -0
- package/package.json +2 -2
- package/src/core/innerLifecycle.js +2 -0
- package/src/core/mergeOptions.js +7 -3
- package/src/core/proxy.js +28 -4
- package/src/index.js +2 -0
- package/src/observer/effect.js +18 -1
- package/src/observer/scheduler.js +8 -5
- package/src/observer/watch.js +1 -3
- package/src/platform/builtInMixins/pageStatusMixin.web.js +21 -19
- package/src/platform/builtInMixins/proxyEventMixin.web.js +1 -1
- package/src/platform/createApp.js +20 -11
- package/src/platform/patch/web/getDefaultOptions.js +4 -1
- package/src/platform/patch/web/lifecycle.js +3 -1
- package/src/platform/patch/wx/lifecycle.js +2 -1
package/@types/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mpxjs/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.0-beta.0",
|
|
4
4
|
"description": "mpx runtime core",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"miniprogram",
|
|
@@ -47,5 +47,5 @@
|
|
|
47
47
|
"url": "https://github.com/didi/mpx/issues"
|
|
48
48
|
},
|
|
49
49
|
"sideEffects": false,
|
|
50
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "67b611aeae99f916d46ca8d5d9ed784ddf53f05c"
|
|
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,
|
package/src/core/mergeOptions.js
CHANGED
|
@@ -132,7 +132,9 @@ function extractObservers (options) {
|
|
|
132
132
|
},
|
|
133
133
|
deep: true,
|
|
134
134
|
// 延迟触发首次回调,处理转换支付宝时在observer中查询组件的行为,如vant/picker中,如不考虑该特殊情形可用immediate代替
|
|
135
|
-
immediateAsync: true
|
|
135
|
+
// immediateAsync: true
|
|
136
|
+
// 为了数据响应的标准化,不再提供immediateAsync选项,之前处理vant等原生组件跨平台转换遇到的问题推荐使用条件编译patch进行处理
|
|
137
|
+
immediate: true
|
|
136
138
|
})
|
|
137
139
|
}
|
|
138
140
|
})
|
|
@@ -174,7 +176,9 @@ function extractObservers (options) {
|
|
|
174
176
|
}
|
|
175
177
|
},
|
|
176
178
|
deep,
|
|
177
|
-
immediateAsync: watchProp
|
|
179
|
+
// immediateAsync: watchProp
|
|
180
|
+
// 为了数据响应的标准化,不再提供immediateAsync选项,之前处理vant等原生组件跨平台转换遇到的问题推荐使用条件编译patch进行处理
|
|
181
|
+
immediate: watchProp
|
|
178
182
|
})
|
|
179
183
|
}
|
|
180
184
|
})
|
|
@@ -348,7 +352,7 @@ function transformHOOKS (options) {
|
|
|
348
352
|
const componentHooksMap = makeMap(convertRule.lifecycle.component)
|
|
349
353
|
for (const key in options) {
|
|
350
354
|
// 使用Component创建page实例,页面专属生命周期&自定义方法需写在methods内部
|
|
351
|
-
if (typeof options[key] === 'function' && key !== 'dataFn' && key !== 'setup' && !componentHooksMap[key]) {
|
|
355
|
+
if (typeof options[key] === 'function' && key !== 'dataFn' && key !== 'setup' && key !== 'serverPrefetch' && !componentHooksMap[key]) {
|
|
352
356
|
if (!options.methods) options.methods = {}
|
|
353
357
|
options.methods[key] = options[key]
|
|
354
358
|
delete options[key]
|
package/src/core/proxy.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { reactive } from '../observer/reactive'
|
|
2
|
-
import { ReactiveEffect } from '../observer/effect'
|
|
2
|
+
import { ReactiveEffect, pauseTracking, resetTracking } from '../observer/effect'
|
|
3
3
|
import { effectScope } from '../platform/export/index'
|
|
4
4
|
import { watch } from '../observer/watch'
|
|
5
5
|
import { computed } from '../observer/computed'
|
|
6
|
-
import { queueJob, nextTick } from '../observer/scheduler'
|
|
6
|
+
import { queueJob, nextTick, flushPreFlushCbs } from '../observer/scheduler'
|
|
7
7
|
import Mpx from '../index'
|
|
8
8
|
import {
|
|
9
9
|
noop,
|
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
BEFOREUPDATE,
|
|
37
37
|
UPDATED,
|
|
38
38
|
BEFOREUNMOUNT,
|
|
39
|
+
SERVERPREFETCH,
|
|
39
40
|
UNMOUNTED,
|
|
40
41
|
ONLOAD,
|
|
41
42
|
ONSHOW,
|
|
@@ -119,6 +120,7 @@ export default class MpxProxy {
|
|
|
119
120
|
// 下次是否需要强制更新全部渲染数据
|
|
120
121
|
this.forceUpdateAll = false
|
|
121
122
|
this.currentRenderTask = null
|
|
123
|
+
this.propsUpdatedFlag = false
|
|
122
124
|
}
|
|
123
125
|
this.initApi()
|
|
124
126
|
}
|
|
@@ -170,7 +172,9 @@ export default class MpxProxy {
|
|
|
170
172
|
}
|
|
171
173
|
|
|
172
174
|
propsUpdated () {
|
|
175
|
+
this.propsUpdatedFlag = true
|
|
173
176
|
const updateJob = this.updateJob || (this.updateJob = () => {
|
|
177
|
+
this.propsUpdatedFlag = false
|
|
174
178
|
// 只有当前没有渲染任务时,属性更新才需要单独触发updated,否则可以由渲染任务触发updated
|
|
175
179
|
if (this.currentRenderTask?.resolved && this.isMounted()) {
|
|
176
180
|
this.callHook(BEFOREUPDATE)
|
|
@@ -477,6 +481,7 @@ export default class MpxProxy {
|
|
|
477
481
|
return
|
|
478
482
|
}
|
|
479
483
|
|
|
484
|
+
pauseTracking()
|
|
480
485
|
// 使用forceUpdateData后清空
|
|
481
486
|
if (!isEmptyObject(this.forceUpdateData)) {
|
|
482
487
|
data = mergeData({}, data, this.forceUpdateData)
|
|
@@ -504,12 +509,30 @@ export default class MpxProxy {
|
|
|
504
509
|
}
|
|
505
510
|
|
|
506
511
|
this.target.__render(data, callback)
|
|
512
|
+
resetTracking()
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
toggleRecurse (allowed) {
|
|
516
|
+
if (this.effect && this.update) this.effect.allowRecurse = this.update.allowRecurse = allowed
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
updatePreRender () {
|
|
520
|
+
this.toggleRecurse(false)
|
|
521
|
+
pauseTracking()
|
|
522
|
+
flushPreFlushCbs(undefined, this.update)
|
|
523
|
+
resetTracking()
|
|
524
|
+
this.toggleRecurse(true)
|
|
507
525
|
}
|
|
508
526
|
|
|
509
527
|
initRender () {
|
|
510
528
|
if (this.options.__nativeRender__) return this.doRender()
|
|
511
529
|
|
|
512
530
|
const effect = this.effect = new ReactiveEffect(() => {
|
|
531
|
+
// pre render for props update
|
|
532
|
+
if (this.propsUpdatedFlag) {
|
|
533
|
+
this.updatePreRender()
|
|
534
|
+
}
|
|
535
|
+
|
|
513
536
|
if (this.target.__injectedRender) {
|
|
514
537
|
try {
|
|
515
538
|
return this.target.__injectedRender()
|
|
@@ -522,10 +545,10 @@ export default class MpxProxy {
|
|
|
522
545
|
}
|
|
523
546
|
}, () => queueJob(update), this.scope)
|
|
524
547
|
|
|
525
|
-
const update = this.update =
|
|
548
|
+
const update = this.update = effect.run.bind(effect)
|
|
526
549
|
update.id = this.uid
|
|
527
550
|
// render effect允许自触发
|
|
528
|
-
|
|
551
|
+
this.toggleRecurse(true)
|
|
529
552
|
update()
|
|
530
553
|
}
|
|
531
554
|
|
|
@@ -619,6 +642,7 @@ export const onLoad = createHook(ONLOAD)
|
|
|
619
642
|
export const onShow = createHook(ONSHOW)
|
|
620
643
|
export const onHide = createHook(ONHIDE)
|
|
621
644
|
export const onResize = createHook(ONRESIZE)
|
|
645
|
+
export const onServerPrefetch = createHook(SERVERPREFETCH)
|
|
622
646
|
export const onPullDownRefresh = createHook('__onPullDownRefresh__')
|
|
623
647
|
export const onReachBottom = createHook('__onReachBottom__')
|
|
624
648
|
export const onShareAppMessage = createHook('__onShareAppMessage__')
|
package/src/index.js
CHANGED
package/src/observer/effect.js
CHANGED
|
@@ -4,6 +4,19 @@ import { PausedState } from '../helper/const'
|
|
|
4
4
|
|
|
5
5
|
let uid = 0
|
|
6
6
|
|
|
7
|
+
let shouldTrack = true
|
|
8
|
+
const trackStack = []
|
|
9
|
+
|
|
10
|
+
export function pauseTracking () {
|
|
11
|
+
trackStack.push(shouldTrack)
|
|
12
|
+
shouldTrack = false
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function resetTracking () {
|
|
16
|
+
const last = trackStack.pop()
|
|
17
|
+
shouldTrack = last === undefined ? true : last
|
|
18
|
+
}
|
|
19
|
+
|
|
7
20
|
export class ReactiveEffect {
|
|
8
21
|
active = true
|
|
9
22
|
deps = []
|
|
@@ -27,17 +40,21 @@ export class ReactiveEffect {
|
|
|
27
40
|
// run fn and return value
|
|
28
41
|
run () {
|
|
29
42
|
if (!this.active) return this.fn()
|
|
30
|
-
|
|
43
|
+
const lastShouldTrack = shouldTrack
|
|
31
44
|
try {
|
|
45
|
+
pushTarget(this)
|
|
46
|
+
shouldTrack = true
|
|
32
47
|
return this.fn()
|
|
33
48
|
} finally {
|
|
34
49
|
popTarget()
|
|
50
|
+
shouldTrack = lastShouldTrack
|
|
35
51
|
this.deferStop ? this.stop() : this.cleanupDeps()
|
|
36
52
|
}
|
|
37
53
|
}
|
|
38
54
|
|
|
39
55
|
// add dependency to this
|
|
40
56
|
addDep (dep) {
|
|
57
|
+
if (!shouldTrack) return
|
|
41
58
|
const id = dep.id
|
|
42
59
|
if (!this.newDepIds.has(id)) {
|
|
43
60
|
this.newDepIds.add(id)
|
|
@@ -17,6 +17,7 @@ let postFlushIndex = 0
|
|
|
17
17
|
|
|
18
18
|
const resolvedPromise = Promise.resolve()
|
|
19
19
|
let currentFlushPromise = null
|
|
20
|
+
let currentPreFlushParentJob = null
|
|
20
21
|
|
|
21
22
|
const RECURSION_LIMIT = 100
|
|
22
23
|
|
|
@@ -68,9 +69,9 @@ export function queueJob (job) {
|
|
|
68
69
|
// if the job is a watch() callback, the search will start with a +1 index to
|
|
69
70
|
// allow it recursively trigger itself - it is the user's responsibility to
|
|
70
71
|
// ensure it doesn't end up in an infinite loop.
|
|
71
|
-
if (
|
|
72
|
-
!queue.
|
|
73
|
-
|
|
72
|
+
if ((!queue.length ||
|
|
73
|
+
!queue.includes(job, isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex)) &&
|
|
74
|
+
job !== currentPreFlushParentJob
|
|
74
75
|
) {
|
|
75
76
|
if (job.id == null) {
|
|
76
77
|
queue.push(job)
|
|
@@ -92,8 +93,9 @@ function queueFlush () {
|
|
|
92
93
|
}
|
|
93
94
|
}
|
|
94
95
|
|
|
95
|
-
export function flushPreFlushCbs (seen) {
|
|
96
|
+
export function flushPreFlushCbs (seen, parentJob = null) {
|
|
96
97
|
if (pendingPreFlushCbs.length) {
|
|
98
|
+
currentPreFlushParentJob = parentJob
|
|
97
99
|
activePreFlushCbs = [...new Set(pendingPreFlushCbs)]
|
|
98
100
|
pendingPreFlushCbs.length = 0
|
|
99
101
|
if (isDev) seen = seen || new Map()
|
|
@@ -107,8 +109,9 @@ export function flushPreFlushCbs (seen) {
|
|
|
107
109
|
}
|
|
108
110
|
activePreFlushCbs = null
|
|
109
111
|
preFlushIndex = 0
|
|
112
|
+
currentPreFlushParentJob = null
|
|
110
113
|
// recursively flush until it drains
|
|
111
|
-
flushPreFlushCbs(seen)
|
|
114
|
+
flushPreFlushCbs(seen, parentJob)
|
|
112
115
|
}
|
|
113
116
|
}
|
|
114
117
|
|
package/src/observer/watch.js
CHANGED
|
@@ -42,7 +42,7 @@ const processWatchOptionsCompat = (options) => {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export function watch (source, cb, options = {}) {
|
|
45
|
-
let { immediate, deep, flush
|
|
45
|
+
let { immediate, deep, flush } = processWatchOptionsCompat(options)
|
|
46
46
|
const instance = currentInstance
|
|
47
47
|
let getter
|
|
48
48
|
let isMultiSource = false
|
|
@@ -139,8 +139,6 @@ export function watch (source, cb, options = {}) {
|
|
|
139
139
|
if (cb) {
|
|
140
140
|
if (immediate) {
|
|
141
141
|
job()
|
|
142
|
-
} else if (immediateAsync) {
|
|
143
|
-
queuePreFlushCb(job)
|
|
144
142
|
} else {
|
|
145
143
|
oldValue = effect.run()
|
|
146
144
|
}
|
|
@@ -63,7 +63,7 @@ export default function pageStatusMixin (mixinType) {
|
|
|
63
63
|
},
|
|
64
64
|
created () {
|
|
65
65
|
// onLoad应该在用户声明周期CREATED后再执行,故此处使用原生created声明周期来触发onLoad
|
|
66
|
-
const query =
|
|
66
|
+
const query = this.$root.$options?.router?.currentRoute?.query || {}
|
|
67
67
|
this.__mpxProxy.callHook(ONLOAD, [query])
|
|
68
68
|
}
|
|
69
69
|
})
|
|
@@ -71,25 +71,27 @@ export default function pageStatusMixin (mixinType) {
|
|
|
71
71
|
|
|
72
72
|
Object.assign(mixin, {
|
|
73
73
|
[CREATED] () {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
74
|
+
if (isBrowser) {
|
|
75
|
+
const pageInstance = mixinType === 'page' ? this : getCurrentPageInstance()
|
|
76
|
+
if (pageInstance) {
|
|
77
|
+
this.$watch(() => pageInstance.mpxPageStatus, status => {
|
|
78
|
+
if (!status) return
|
|
79
|
+
if (status === 'show') this.__mpxProxy.callHook(ONSHOW)
|
|
80
|
+
if (status === 'hide') this.__mpxProxy.callHook(ONHIDE)
|
|
81
|
+
const pageLifetimes = this.__mpxProxy.options.pageLifetimes
|
|
82
|
+
if (pageLifetimes) {
|
|
83
|
+
if (/^resize/.test(status) && isFunction(pageLifetimes.resize)) {
|
|
84
|
+
// resize
|
|
85
|
+
pageLifetimes.resize.call(this, systemInfo)
|
|
86
|
+
} else if (isFunction(pageLifetimes[status])) {
|
|
87
|
+
// show & hide
|
|
88
|
+
pageLifetimes[status].call(this)
|
|
89
|
+
}
|
|
88
90
|
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
91
|
+
}, {
|
|
92
|
+
sync: true
|
|
93
|
+
})
|
|
94
|
+
}
|
|
93
95
|
}
|
|
94
96
|
}
|
|
95
97
|
})
|
|
@@ -20,7 +20,7 @@ export default function proxyEventMixin () {
|
|
|
20
20
|
setByPath(this, expr, value)
|
|
21
21
|
},
|
|
22
22
|
getOpenerEventChannel () {
|
|
23
|
-
const router =
|
|
23
|
+
const router = this.$root.$options && this.$root.$options.router
|
|
24
24
|
const eventChannel = router && router.__mpxAction && router.__mpxAction.eventChannel
|
|
25
25
|
return eventChannel
|
|
26
26
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
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
5
|
import * as webLifecycle from '../platform/patch/web/lifecycle'
|
|
6
6
|
import Mpx from '../index'
|
|
7
7
|
|
|
@@ -35,7 +35,7 @@ export default function createApp (option, config = {}) {
|
|
|
35
35
|
created () {
|
|
36
36
|
Object.assign(this, Mpx.prototype)
|
|
37
37
|
Object.assign(this, appData)
|
|
38
|
-
const current =
|
|
38
|
+
const current = this.$root.$options?.router?.currentRoute || {}
|
|
39
39
|
const options = {
|
|
40
40
|
path: current.path && current.path.replace(/^\//, ''),
|
|
41
41
|
query: current.query,
|
|
@@ -49,19 +49,24 @@ export default function createApp (option, config = {}) {
|
|
|
49
49
|
hide: [],
|
|
50
50
|
error: []
|
|
51
51
|
}
|
|
52
|
-
if (
|
|
53
|
-
this.$options.onShow
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
if (isBrowser) {
|
|
53
|
+
if (this.$options.onShow) {
|
|
54
|
+
this.$options.onShow.call(this, options)
|
|
55
|
+
global.__mpxAppCbs.show.push(this.$options.onShow.bind(this))
|
|
56
|
+
}
|
|
57
|
+
if (this.$options.onHide) {
|
|
58
|
+
global.__mpxAppCbs.hide.push(this.$options.onHide.bind(this))
|
|
59
|
+
}
|
|
60
|
+
if (this.$options.onError) {
|
|
61
|
+
global.__mpxAppCbs.error.push(this.$options.onError.bind(this))
|
|
62
|
+
}
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
})
|
|
64
66
|
} else {
|
|
67
|
+
if (option.onAppInit) {
|
|
68
|
+
option.onAppInit()
|
|
69
|
+
}
|
|
65
70
|
builtInMixins.push({
|
|
66
71
|
onLaunch () {
|
|
67
72
|
Object.assign(this, Mpx.prototype)
|
|
@@ -77,6 +82,10 @@ export default function createApp (option, config = {}) {
|
|
|
77
82
|
global.__mpxOptionsMap = global.__mpxOptionsMap || {}
|
|
78
83
|
global.__mpxOptionsMap[global.currentModuleId] = defaultOptions
|
|
79
84
|
global.getApp = function () {
|
|
85
|
+
if (!isBrowser) {
|
|
86
|
+
console.error('[Mpx runtime error]: Dangerous API! global.getApp method is running in non browser environments')
|
|
87
|
+
return
|
|
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) this.__mpxProxy.callHook(SERVERPREFETCH)
|
|
82
85
|
}
|
|
83
86
|
}]
|
|
84
87
|
// 为了在builtMixin中可以使用某些rootMixin实现的特性(如数据响应等),此处builtInMixin在rootMixin之后执行,但是当builtInMixin使用存在对应内建生命周期的目标平台声明周期写法时,可能会出现用户生命周期比builtInMixin中的生命周期先执行的情况,为了避免这种情况发生,builtInMixin应该尽可能使用内建生命周期来编写
|