@mpxjs/core 2.7.52 → 2.8.0-beta.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 +342 -27
- package/package.json +10 -5
- package/src/convertor/convertor.js +2 -2
- package/src/convertor/mergeLifecycle.js +4 -4
- package/src/convertor/wxToAli.js +3 -4
- package/src/convertor/wxToSwan.js +2 -2
- package/src/convertor/wxToTt.js +1 -10
- package/src/convertor/wxToWeb.js +14 -7
- package/src/core/implement.js +2 -2
- package/src/core/injectMixins.js +1 -1
- package/src/core/innerLifecycle.js +15 -2
- package/src/core/mergeOptions.js +11 -5
- package/src/core/proxy.js +343 -229
- package/src/core/transferOptions.js +5 -2
- package/src/helper/const.js +10 -0
- package/src/index.js +73 -147
- package/src/observer/array.js +12 -17
- package/src/observer/computed.js +27 -56
- package/src/observer/dep.js +1 -1
- package/src/observer/effect.js +113 -0
- package/src/observer/effectScope.js +109 -0
- package/src/observer/{index.js → reactive.js} +74 -70
- package/src/observer/ref.js +97 -0
- package/src/observer/scheduler.js +171 -56
- package/src/observer/watch.js +163 -39
- package/src/platform/builtInMixins/i18nMixin.js +238 -31
- package/src/platform/builtInMixins/pageScrollMixin.web.js +4 -5
- package/src/platform/builtInMixins/pageStatusMixin.js +76 -54
- package/src/platform/builtInMixins/pageStatusMixin.web.js +35 -22
- package/src/platform/builtInMixins/proxyEventMixin.js +40 -22
- package/src/platform/builtInMixins/proxyEventMixin.web.js +16 -24
- package/src/platform/builtInMixins/refsMixin.js +82 -73
- package/src/platform/builtInMixins/refsMixin.web.js +0 -47
- package/src/platform/builtInMixins/relationsMixin.js +10 -9
- package/src/platform/builtInMixins/renderHelperMixin.js +1 -1
- package/src/platform/builtInMixins/showMixin.js +1 -1
- package/src/platform/createApp.js +5 -5
- package/src/platform/export/api.js +23 -0
- package/src/platform/export/api.web.js +26 -0
- package/src/platform/export/index.js +45 -0
- package/src/platform/export/index.web.js +36 -0
- package/src/platform/index.js +1 -5
- package/src/platform/patch/ali/getDefaultOptions.js +33 -31
- package/src/platform/patch/ali/lifecycle.js +21 -13
- package/src/platform/patch/builtInKeysMap.js +2 -1
- package/src/platform/patch/index.js +4 -9
- package/src/platform/patch/swan/getDefaultOptions.js +3 -3
- package/src/platform/patch/swan/lifecycle.js +17 -14
- package/src/platform/patch/web/getDefaultOptions.js +40 -16
- package/src/platform/patch/web/lifecycle.js +6 -3
- package/src/platform/patch/wx/getDefaultOptions.js +38 -31
- package/src/platform/patch/wx/lifecycle.js +18 -11
- package/src/runtime/createFactory.js +6 -2
- package/src/vue.web.js +3 -0
- package/src/vuePlugin.js +31 -0
- package/src/core/createStore.js +0 -241
- package/src/core/mapStore.js +0 -94
- package/src/helper/env.js +0 -20
- package/src/helper/getByPath.js +0 -127
- package/src/helper/log.js +0 -31
- package/src/helper/utils.js +0 -652
- package/src/observer/watcher.js +0 -244
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { mergeInjectedMixins } from './injectMixins'
|
|
2
2
|
import mergeOptions from './mergeOptions'
|
|
3
3
|
import { getConvertMode } from '../convertor/getConvertMode'
|
|
4
|
-
import { findItem } from '
|
|
5
|
-
import { warn } from '../helper/log'
|
|
4
|
+
import { warn, findItem } from '@mpxjs/utils'
|
|
6
5
|
|
|
7
6
|
export default function transferOptions (options, type) {
|
|
8
7
|
let currentInject
|
|
@@ -23,6 +22,10 @@ export default function transferOptions (options, type) {
|
|
|
23
22
|
// 编译option注入,优先微信中的单独配置
|
|
24
23
|
options.options = Object.assign({}, currentInject.injectOptions, options.options)
|
|
25
24
|
}
|
|
25
|
+
if (currentInject && currentInject.pageEvents) {
|
|
26
|
+
options.mixins = options.mixins || []
|
|
27
|
+
options.mixins.unshift(currentInject.pageEvents)
|
|
28
|
+
}
|
|
26
29
|
// 转换mode
|
|
27
30
|
options.mpxConvertMode = options.mpxConvertMode || getConvertMode(global.currentSrcMode)
|
|
28
31
|
const rawOptions = mergeOptions(options, type)
|
package/src/index.js
CHANGED
|
@@ -1,44 +1,62 @@
|
|
|
1
|
-
import * as platform from './platform'
|
|
2
|
-
import createStore, {
|
|
3
|
-
createStoreWithThis,
|
|
4
|
-
createStateWithThis,
|
|
5
|
-
createGettersWithThis,
|
|
6
|
-
createMutationsWithThis,
|
|
7
|
-
createActionsWithThis
|
|
8
|
-
} from './core/createStore'
|
|
9
|
-
import { injectMixins } from './core/injectMixins'
|
|
10
|
-
import { extend, diffAndCloneA, makeMap, merge, hasOwn } from './helper/utils'
|
|
11
|
-
import { getMixin } from './core/mergeOptions'
|
|
12
|
-
import { error } from './helper/log'
|
|
13
1
|
import Vue from './vue'
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import implement from './core/implement'
|
|
2
|
+
import { error, diffAndCloneA, hasOwn, makeMap } from '@mpxjs/utils'
|
|
3
|
+
import { APIs, InstanceAPIs } from './platform/export/api'
|
|
17
4
|
|
|
18
|
-
|
|
19
|
-
const mpx = new EXPORT_MPX()
|
|
20
|
-
platform.createApp(Object.assign({ proto: mpx.proto }, config), ...rest)
|
|
21
|
-
}
|
|
5
|
+
import { createI18n } from './platform/builtInMixins/i18nMixin'
|
|
22
6
|
|
|
23
|
-
export
|
|
24
|
-
const mpx = new EXPORT_MPX()
|
|
25
|
-
platform.createPage(Object.assign({ proto: mpx.proto }, config), ...rest)
|
|
26
|
-
}
|
|
7
|
+
export * from './platform/export/index'
|
|
27
8
|
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
9
|
+
export * from '@mpxjs/store'
|
|
10
|
+
|
|
11
|
+
export { implement } from './core/implement'
|
|
32
12
|
|
|
33
13
|
export {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}
|
|
14
|
+
createApp,
|
|
15
|
+
createPage,
|
|
16
|
+
createComponent
|
|
17
|
+
} from './platform/index'
|
|
18
|
+
|
|
19
|
+
export {
|
|
20
|
+
nextTick
|
|
21
|
+
} from './observer/scheduler'
|
|
22
|
+
|
|
23
|
+
export {
|
|
24
|
+
BEFORECREATE,
|
|
25
|
+
CREATED,
|
|
26
|
+
BEFOREMOUNT,
|
|
27
|
+
MOUNTED,
|
|
28
|
+
BEFOREUPDATE,
|
|
29
|
+
UPDATED,
|
|
30
|
+
BEFOREUNMOUNT,
|
|
31
|
+
UNMOUNTED,
|
|
32
|
+
ONLOAD,
|
|
33
|
+
ONSHOW,
|
|
34
|
+
ONHIDE,
|
|
35
|
+
ONRESIZE
|
|
36
|
+
} from './core/innerLifecycle'
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
onBeforeMount,
|
|
40
|
+
onMounted,
|
|
41
|
+
onBeforeUpdate,
|
|
42
|
+
onUpdated,
|
|
43
|
+
onBeforeUnmount,
|
|
44
|
+
onUnmounted,
|
|
45
|
+
onLoad,
|
|
46
|
+
onShow,
|
|
47
|
+
onHide,
|
|
48
|
+
onResize,
|
|
49
|
+
onPullDownRefresh,
|
|
50
|
+
onReachBottom,
|
|
51
|
+
onShareAppMessage,
|
|
52
|
+
onShareTimeline,
|
|
53
|
+
onAddToFavorites,
|
|
54
|
+
onPageScroll,
|
|
55
|
+
onTabItemTap,
|
|
56
|
+
onSaveExitState
|
|
57
|
+
} from './core/proxy'
|
|
58
|
+
|
|
59
|
+
export { getMixin } from './core/mergeOptions'
|
|
42
60
|
|
|
43
61
|
export function toPureObject (obj) {
|
|
44
62
|
return diffAndCloneA(obj).clone
|
|
@@ -73,151 +91,59 @@ function use (plugin, options = {}) {
|
|
|
73
91
|
}
|
|
74
92
|
|
|
75
93
|
const args = [options]
|
|
76
|
-
const
|
|
77
|
-
const rawProps = Object.getOwnPropertyNames(
|
|
78
|
-
const rawPrototypeProps = Object.getOwnPropertyNames(
|
|
79
|
-
args.unshift(
|
|
94
|
+
const proxyMpx = factory()
|
|
95
|
+
const rawProps = Object.getOwnPropertyNames(proxyMpx)
|
|
96
|
+
const rawPrototypeProps = Object.getOwnPropertyNames(proxyMpx.prototype)
|
|
97
|
+
args.unshift(proxyMpx)
|
|
80
98
|
// 传入真正的mpx对象供插件访问
|
|
81
|
-
args.push(
|
|
99
|
+
args.push(Mpx)
|
|
82
100
|
if (typeof plugin.install === 'function') {
|
|
83
101
|
plugin.install.apply(plugin, args)
|
|
84
102
|
} else if (typeof plugin === 'function') {
|
|
85
103
|
plugin.apply(null, args)
|
|
86
104
|
}
|
|
87
|
-
extendProps(
|
|
88
|
-
extendProps(
|
|
105
|
+
extendProps(Mpx, proxyMpx, rawProps, options)
|
|
106
|
+
extendProps(Mpx.prototype, proxyMpx.prototype, rawPrototypeProps, options)
|
|
89
107
|
installedPlugins.push(plugin)
|
|
90
108
|
return this
|
|
91
109
|
}
|
|
92
110
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// 实例属性
|
|
96
|
-
let InstanceAPIs = {}
|
|
97
|
-
|
|
98
|
-
let observable
|
|
99
|
-
let watch
|
|
100
|
-
|
|
101
|
-
if (__mpx_mode__ === 'web') {
|
|
102
|
-
const vm = new Vue()
|
|
103
|
-
observable = Vue.observable.bind(Vue)
|
|
104
|
-
watch = vm.$watch.bind(vm)
|
|
105
|
-
const set = Vue.set.bind(Vue)
|
|
106
|
-
const del = Vue.delete.bind(Vue)
|
|
107
|
-
APIs = {
|
|
108
|
-
createApp,
|
|
109
|
-
createPage,
|
|
110
|
-
createComponent,
|
|
111
|
-
createStore,
|
|
112
|
-
createStoreWithThis,
|
|
113
|
-
mixin: injectMixins,
|
|
114
|
-
injectMixins,
|
|
115
|
-
toPureObject,
|
|
116
|
-
observable,
|
|
117
|
-
watch,
|
|
118
|
-
use,
|
|
119
|
-
set,
|
|
120
|
-
delete: del,
|
|
121
|
-
getMixin,
|
|
122
|
-
implement
|
|
123
|
-
}
|
|
124
|
-
} else {
|
|
125
|
-
observable = function (obj) {
|
|
126
|
-
observe(obj)
|
|
127
|
-
return obj
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const vm = {}
|
|
131
|
-
watch = function (expOrFn, cb, options) {
|
|
132
|
-
return watchWithVm(vm, expOrFn, cb, options)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
APIs = {
|
|
136
|
-
createApp,
|
|
137
|
-
createPage,
|
|
138
|
-
createComponent,
|
|
139
|
-
createStore,
|
|
140
|
-
createStoreWithThis,
|
|
141
|
-
mixin: injectMixins,
|
|
142
|
-
injectMixins,
|
|
143
|
-
toPureObject,
|
|
144
|
-
observable,
|
|
145
|
-
watch,
|
|
146
|
-
use,
|
|
147
|
-
set,
|
|
148
|
-
delete: del,
|
|
149
|
-
getMixin,
|
|
150
|
-
implement
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
InstanceAPIs = {
|
|
154
|
-
$set: set,
|
|
155
|
-
$delete: del
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export { watch, observable }
|
|
111
|
+
APIs.use = use
|
|
160
112
|
|
|
161
113
|
function factory () {
|
|
162
114
|
// 作为原型挂载属性的中间层
|
|
163
|
-
function
|
|
164
|
-
this.proto = extend({}, this)
|
|
115
|
+
function Mpx () {
|
|
165
116
|
}
|
|
166
117
|
|
|
167
|
-
Object.assign(
|
|
168
|
-
Object.assign(
|
|
118
|
+
Object.assign(Mpx, APIs)
|
|
119
|
+
Object.assign(Mpx.prototype, InstanceAPIs)
|
|
169
120
|
// 输出web时在mpx上挂载Vue对象
|
|
170
121
|
if (__mpx_mode__ === 'web') {
|
|
171
|
-
|
|
122
|
+
Mpx.__vue = Vue
|
|
172
123
|
}
|
|
173
|
-
return
|
|
124
|
+
return Mpx
|
|
174
125
|
}
|
|
175
126
|
|
|
176
|
-
const
|
|
127
|
+
const Mpx = factory()
|
|
177
128
|
|
|
178
|
-
|
|
129
|
+
Mpx.config = {
|
|
179
130
|
useStrictDiff: false,
|
|
180
131
|
ignoreWarning: false,
|
|
181
132
|
ignoreProxyWhiteList: ['id', 'dataset', 'data'],
|
|
182
133
|
observeClassInstance: false,
|
|
183
|
-
|
|
134
|
+
errorHandler: null,
|
|
184
135
|
proxyEventHandler: null,
|
|
185
136
|
setDataHandler: null,
|
|
186
|
-
|
|
137
|
+
forceFlushSync: false,
|
|
187
138
|
webRouteConfig: {}
|
|
188
139
|
}
|
|
189
140
|
|
|
190
|
-
global.__mpx =
|
|
141
|
+
global.__mpx = Mpx
|
|
191
142
|
|
|
192
143
|
if (__mpx_mode__ !== 'web') {
|
|
193
144
|
if (global.i18n) {
|
|
194
|
-
|
|
195
|
-
// 挂载翻译方法
|
|
196
|
-
if (global.i18nMethods) {
|
|
197
|
-
Object.keys(global.i18nMethods).forEach((methodName) => {
|
|
198
|
-
if (/^__/.test(methodName)) return
|
|
199
|
-
global.i18n[methodName] = (...args) => {
|
|
200
|
-
// tap i18n.version
|
|
201
|
-
args.unshift((global.i18n.version, global.i18n.locale))
|
|
202
|
-
return global.i18nMethods[methodName].apply(this, args)
|
|
203
|
-
}
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
if (global.i18nMethods.__getMessages) {
|
|
207
|
-
const messages = global.i18nMethods.__getMessages()
|
|
208
|
-
global.i18n.mergeMessages = (newMessages) => {
|
|
209
|
-
merge(messages, newMessages)
|
|
210
|
-
global.i18n.version++
|
|
211
|
-
}
|
|
212
|
-
global.i18n.mergeLocaleMessage = (locale, message) => {
|
|
213
|
-
messages[locale] = messages[locale] || {}
|
|
214
|
-
merge(messages[locale], message)
|
|
215
|
-
global.i18n.version++
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
EXPORT_MPX.i18n = global.i18n
|
|
145
|
+
Mpx.i18n = createI18n(global.i18n)
|
|
220
146
|
}
|
|
221
147
|
}
|
|
222
148
|
|
|
223
|
-
export default
|
|
149
|
+
export default Mpx
|
package/src/observer/array.js
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
* dynamically accessing methods on Array prototype
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { def } from '../helper/utils'
|
|
1
|
+
import { getObserver } from './reactive'
|
|
2
|
+
import { def } from '@mpxjs/utils'
|
|
7
3
|
|
|
8
4
|
const arrayProto = Array.prototype
|
|
5
|
+
|
|
9
6
|
export const arrayMethods = Object.create(arrayProto)
|
|
10
7
|
|
|
11
|
-
/**
|
|
12
|
-
* Intercept mutating methods and emit events
|
|
13
|
-
*/
|
|
14
8
|
;[
|
|
15
9
|
'push',
|
|
16
10
|
'pop',
|
|
@@ -19,13 +13,13 @@ export const arrayMethods = Object.create(arrayProto)
|
|
|
19
13
|
'splice',
|
|
20
14
|
'sort',
|
|
21
15
|
'reverse'
|
|
22
|
-
]
|
|
23
|
-
.forEach(function (method) {
|
|
16
|
+
].forEach(function (method) {
|
|
24
17
|
// cache original method
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
const original = arrayProto[method]
|
|
19
|
+
def(arrayMethods, method, function mutator (...args) {
|
|
20
|
+
const result = original.apply(this, args)
|
|
21
|
+
const ob = getObserver(this)
|
|
22
|
+
if (ob) {
|
|
29
23
|
let inserted
|
|
30
24
|
switch (method) {
|
|
31
25
|
case 'push':
|
|
@@ -39,6 +33,7 @@ export const arrayMethods = Object.create(arrayProto)
|
|
|
39
33
|
if (inserted) ob.observeArray(inserted)
|
|
40
34
|
// notify change
|
|
41
35
|
ob.dep.notify()
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
}
|
|
37
|
+
return result
|
|
44
38
|
})
|
|
39
|
+
})
|
package/src/observer/computed.js
CHANGED
|
@@ -1,66 +1,37 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { noop } from '../helper/utils'
|
|
3
|
-
import { error } from '../helper/log'
|
|
1
|
+
import { isFunction, noop } from '@mpxjs/utils'
|
|
4
2
|
import Dep from './dep'
|
|
3
|
+
import { createRef } from './ref'
|
|
4
|
+
import { ReactiveEffect } from './effect'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function initComputed (vm, target, computed) {
|
|
14
|
-
const watchers = vm._computedWatchers = {}
|
|
15
|
-
for (const key in computed) {
|
|
16
|
-
const userDef = computed[key]
|
|
17
|
-
const getter = typeof userDef === 'function' ? userDef : userDef.get
|
|
18
|
-
watchers[key] = new Watcher(vm,
|
|
19
|
-
getter || noop,
|
|
20
|
-
noop,
|
|
21
|
-
{ lazy: true }
|
|
22
|
-
)
|
|
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
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function defineComputed (
|
|
34
|
-
vm,
|
|
35
|
-
target,
|
|
36
|
-
key,
|
|
37
|
-
userDef
|
|
38
|
-
) {
|
|
39
|
-
if (typeof userDef === 'function') {
|
|
40
|
-
sharedPropertyDefinition.get = createComputedGetter(vm, key)
|
|
41
|
-
sharedPropertyDefinition.set = noop
|
|
6
|
+
export function computed (getterOrOptions) {
|
|
7
|
+
let getter, setter
|
|
8
|
+
if (isFunction(getterOrOptions)) {
|
|
9
|
+
getter = getterOrOptions
|
|
10
|
+
setter = noop
|
|
42
11
|
} else {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
: noop
|
|
46
|
-
sharedPropertyDefinition.set = userDef.set
|
|
47
|
-
? userDef.set.bind(vm.target)
|
|
48
|
-
: noop
|
|
12
|
+
getter = getterOrOptions.get
|
|
13
|
+
setter = getterOrOptions.set
|
|
49
14
|
}
|
|
50
|
-
|
|
51
|
-
|
|
15
|
+
// 复用createRef创建computedRef,使用闭包变量存储dirty/value/effect
|
|
16
|
+
let dirty = true
|
|
17
|
+
let value
|
|
18
|
+
const effect = new ReactiveEffect(getter, () => {
|
|
19
|
+
dirty = true
|
|
20
|
+
})
|
|
52
21
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
watcher.evaluate()
|
|
22
|
+
return createRef({
|
|
23
|
+
get: () => {
|
|
24
|
+
if (dirty) {
|
|
25
|
+
value = effect.run()
|
|
26
|
+
dirty = false
|
|
59
27
|
}
|
|
60
28
|
if (Dep.target) {
|
|
61
|
-
|
|
29
|
+
effect.depend()
|
|
62
30
|
}
|
|
63
|
-
return
|
|
31
|
+
return value
|
|
32
|
+
},
|
|
33
|
+
set: (val) => {
|
|
34
|
+
setter(val)
|
|
64
35
|
}
|
|
65
|
-
}
|
|
36
|
+
}, effect)
|
|
66
37
|
}
|
package/src/observer/dep.js
CHANGED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import Dep, { pushTarget, popTarget } from './dep'
|
|
2
|
+
import { recordEffectScope } from './effectScope'
|
|
3
|
+
import { PausedState } from '../helper/const'
|
|
4
|
+
|
|
5
|
+
let uid = 0
|
|
6
|
+
|
|
7
|
+
export class ReactiveEffect {
|
|
8
|
+
active = true
|
|
9
|
+
deps = []
|
|
10
|
+
newDeps = []
|
|
11
|
+
depIds = new Set()
|
|
12
|
+
newDepIds = new Set()
|
|
13
|
+
|
|
14
|
+
constructor (
|
|
15
|
+
fn,
|
|
16
|
+
scheduler,
|
|
17
|
+
scope
|
|
18
|
+
) {
|
|
19
|
+
this.id = ++uid
|
|
20
|
+
this.fn = fn
|
|
21
|
+
this.scheduler = scheduler
|
|
22
|
+
this.pausedState = PausedState.resumed
|
|
23
|
+
recordEffectScope(this, scope)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// run fn and return value
|
|
27
|
+
run () {
|
|
28
|
+
if (!this.active) return this.fn()
|
|
29
|
+
pushTarget(this)
|
|
30
|
+
try {
|
|
31
|
+
return this.fn()
|
|
32
|
+
} finally {
|
|
33
|
+
popTarget()
|
|
34
|
+
this.deferStop ? this.stop() : this.cleanupDeps()
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// add dependency to this
|
|
39
|
+
addDep (dep) {
|
|
40
|
+
const id = dep.id
|
|
41
|
+
if (!this.newDepIds.has(id)) {
|
|
42
|
+
this.newDepIds.add(id)
|
|
43
|
+
this.newDeps.push(dep)
|
|
44
|
+
if (!this.depIds.has(id)) {
|
|
45
|
+
dep.addSub(this)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Clean up for dependency collection.
|
|
51
|
+
cleanupDeps () {
|
|
52
|
+
let i = this.deps.length
|
|
53
|
+
while (i--) {
|
|
54
|
+
const dep = this.deps[i]
|
|
55
|
+
if (!this.newDepIds.has(dep.id)) {
|
|
56
|
+
dep.removeSub(this)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
let tmp = this.depIds
|
|
60
|
+
this.depIds = this.newDepIds
|
|
61
|
+
this.newDepIds = tmp
|
|
62
|
+
this.newDepIds.clear()
|
|
63
|
+
tmp = this.deps
|
|
64
|
+
this.deps = this.newDeps
|
|
65
|
+
this.newDeps = tmp
|
|
66
|
+
this.newDeps.length = 0
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// same as trigger
|
|
70
|
+
update () {
|
|
71
|
+
// avoid dead cycle
|
|
72
|
+
if (Dep.target === this) return
|
|
73
|
+
if (this.pausedState !== PausedState.resumed) {
|
|
74
|
+
this.pausedState = PausedState.dirty
|
|
75
|
+
} else {
|
|
76
|
+
this.scheduler ? this.scheduler() : this.run()
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// pass through deps for computed
|
|
81
|
+
depend () {
|
|
82
|
+
let i = this.deps.length
|
|
83
|
+
while (i--) {
|
|
84
|
+
this.deps[i].depend()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Remove self from all dependencies' subscriber list.
|
|
89
|
+
stop () {
|
|
90
|
+
if (Dep.target === this) {
|
|
91
|
+
this.deferStop = true
|
|
92
|
+
} else if (this.active) {
|
|
93
|
+
let i = this.deps.length
|
|
94
|
+
while (i--) {
|
|
95
|
+
this.deps[i].removeSub(this)
|
|
96
|
+
}
|
|
97
|
+
typeof this.onStop === 'function' && this.onStop()
|
|
98
|
+
this.active = false
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
pause () {
|
|
103
|
+
this.pausedState = PausedState.paused
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
resume () {
|
|
107
|
+
const lastPausedState = this.pausedState
|
|
108
|
+
this.pausedState = PausedState.resumed
|
|
109
|
+
if (lastPausedState === PausedState.dirty) {
|
|
110
|
+
this.scheduler ? this.scheduler() : this.run()
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
let activeEffectScope
|
|
2
|
+
|
|
3
|
+
class EffectScope {
|
|
4
|
+
active = true
|
|
5
|
+
effects = []
|
|
6
|
+
cleanups = []
|
|
7
|
+
|
|
8
|
+
constructor (detached) {
|
|
9
|
+
if (!detached && activeEffectScope) {
|
|
10
|
+
this.parent = activeEffectScope
|
|
11
|
+
this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push(this) - 1
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
run (fn) {
|
|
16
|
+
if (this.active) {
|
|
17
|
+
const currentEffectScope = activeEffectScope
|
|
18
|
+
try {
|
|
19
|
+
activeEffectScope = this
|
|
20
|
+
return fn()
|
|
21
|
+
} finally {
|
|
22
|
+
activeEffectScope = currentEffectScope
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
on () {
|
|
28
|
+
activeEffectScope = this
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
off () {
|
|
32
|
+
activeEffectScope = this.parent
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
stop (fromParent) {
|
|
36
|
+
if (this.active) {
|
|
37
|
+
let i, l
|
|
38
|
+
for (i = 0, l = this.effects.length; i < l; i++) {
|
|
39
|
+
this.effects[i].stop()
|
|
40
|
+
}
|
|
41
|
+
for (i = 0, l = this.cleanups.length; i < l; i++) {
|
|
42
|
+
this.cleanups[i]()
|
|
43
|
+
}
|
|
44
|
+
if (this.scopes) {
|
|
45
|
+
for (i = 0, l = this.scopes.length; i < l; i++) {
|
|
46
|
+
this.scopes[i].stop(true)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// nested scope, dereference from parent to avoid memory leaks
|
|
50
|
+
if (this.parent && !fromParent) {
|
|
51
|
+
// optimized O(1) removal
|
|
52
|
+
const last = this.parent.scopes.pop()
|
|
53
|
+
if (last && last !== this) {
|
|
54
|
+
this.parent.scopes[this.index] = last
|
|
55
|
+
last.index = this.index
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
this.active = false
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
pause () {
|
|
63
|
+
if (this.active) {
|
|
64
|
+
let i, l
|
|
65
|
+
for (i = 0, l = this.effects.length; i < l; i++) {
|
|
66
|
+
this.effects[i].pause()
|
|
67
|
+
}
|
|
68
|
+
if (this.scopes) {
|
|
69
|
+
for (i = 0, l = this.scopes.length; i < l; i++) {
|
|
70
|
+
this.scopes[i].pause()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
resume () {
|
|
77
|
+
if (this.active) {
|
|
78
|
+
let i, l
|
|
79
|
+
for (i = 0, l = this.effects.length; i < l; i++) {
|
|
80
|
+
this.effects[i].resume()
|
|
81
|
+
}
|
|
82
|
+
if (this.scopes) {
|
|
83
|
+
for (i = 0, l = this.scopes.length; i < l; i++) {
|
|
84
|
+
this.scopes[i].resume()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function effectScope (detached) {
|
|
92
|
+
return new EffectScope(detached)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function recordEffectScope (effect, scope = activeEffectScope) {
|
|
96
|
+
if (scope && scope.active) {
|
|
97
|
+
scope.effects.push(effect)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function getCurrentScope () {
|
|
102
|
+
return activeEffectScope
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function onScopeDispose (fn) {
|
|
106
|
+
if (activeEffectScope) {
|
|
107
|
+
activeEffectScope.cleanups.push(fn)
|
|
108
|
+
}
|
|
109
|
+
}
|