vue 2.7.2 → 2.7.5
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/dist/vue.common.dev.js +3395 -3308
- package/dist/vue.common.prod.js +3 -3
- package/dist/vue.esm.browser.js +3351 -3265
- package/dist/vue.esm.browser.min.js +3 -3
- package/dist/vue.esm.js +3628 -3539
- package/dist/vue.js +3408 -3318
- package/dist/vue.min.js +3 -3
- package/dist/vue.runtime.common.dev.js +2788 -2701
- package/dist/vue.runtime.common.prod.js +3 -3
- package/dist/vue.runtime.esm.js +2737 -2648
- package/dist/vue.runtime.js +2810 -2720
- package/dist/vue.runtime.min.js +3 -3
- package/dist/vue.runtime.mjs +73 -8604
- package/package.json +2 -2
- package/packages/compiler-sfc/dist/compiler-sfc.js +1004 -1000
- package/packages/compiler-sfc/package.json +1 -1
- package/packages/compiler-sfc/src/parseComponent.ts +7 -4
- package/packages/compiler-sfc/test/parseComponent.spec.ts +6 -7
- package/src/core/components/keep-alive.ts +5 -4
- package/src/core/global-api/extend.ts +3 -1
- package/src/core/instance/init.ts +1 -1
- package/src/core/instance/lifecycle.ts +8 -3
- package/src/core/instance/render-helpers/render-static.ts +1 -1
- package/src/core/observer/index.ts +54 -55
- package/src/core/observer/traverse.ts +3 -0
- package/src/core/util/debug.ts +2 -1
- package/src/core/vdom/create-component.ts +5 -1
- package/src/platforms/web/runtime/components/transition-group.ts +2 -1
- package/src/shared/constants.ts +3 -1
- package/src/v3/apiAsyncComponent.ts +117 -0
- package/src/v3/apiWatch.ts +6 -8
- package/src/v3/index.ts +6 -0
- package/src/v3/reactivity/reactive.ts +13 -2
- package/src/v3/reactivity/ref.ts +17 -4
- package/types/jsx.d.ts +6 -0
- package/types/options.d.ts +5 -3
- package/types/v3-component-public-instance.d.ts +36 -32
- package/types/v3-define-async-component.d.ts +26 -0
- package/types/v3-define-component.d.ts +25 -1
- package/types/v3-generated.d.ts +23 -0
- package/types/vue.d.ts +27 -12
|
@@ -10,7 +10,6 @@ export const DEFAULT_FILENAME = 'anonymous.vue'
|
|
|
10
10
|
const splitRE = /\r?\n/g
|
|
11
11
|
const replaceRE = /./g
|
|
12
12
|
const isSpecialTag = makeMap('script,style,template', true)
|
|
13
|
-
const isNeedIndentLang = makeMap('pug,jade')
|
|
14
13
|
|
|
15
14
|
export interface SFCCustomBlock {
|
|
16
15
|
type: string
|
|
@@ -179,9 +178,13 @@ export function parseComponent(
|
|
|
179
178
|
currentBlock.end = start
|
|
180
179
|
let text = source.slice(currentBlock.start, currentBlock.end)
|
|
181
180
|
if (
|
|
182
|
-
options.deindent ||
|
|
183
|
-
//
|
|
184
|
-
(
|
|
181
|
+
options.deindent === true ||
|
|
182
|
+
// by default, deindent unless it's script with default lang or ts
|
|
183
|
+
(options.deindent !== false &&
|
|
184
|
+
!(
|
|
185
|
+
currentBlock.type === 'script' &&
|
|
186
|
+
(!currentBlock.lang || currentBlock.lang === 'ts')
|
|
187
|
+
))
|
|
185
188
|
) {
|
|
186
189
|
text = deindent(text)
|
|
187
190
|
}
|
|
@@ -25,8 +25,7 @@ describe('Single File Component parser', () => {
|
|
|
25
25
|
<div>
|
|
26
26
|
<style>nested should be ignored</style>
|
|
27
27
|
</div>
|
|
28
|
-
|
|
29
|
-
{ deindent: true }
|
|
28
|
+
`
|
|
30
29
|
)
|
|
31
30
|
expect(res.template!.content.trim()).toBe('<div>hi</div>')
|
|
32
31
|
expect(res.styles.length).toBe(4)
|
|
@@ -76,8 +75,7 @@ describe('Single File Component parser', () => {
|
|
|
76
75
|
</style>
|
|
77
76
|
`
|
|
78
77
|
const deindentDefault = parseComponent(content.trim(), {
|
|
79
|
-
pad: false
|
|
80
|
-
deindent: true
|
|
78
|
+
pad: false
|
|
81
79
|
})
|
|
82
80
|
const deindentEnabled = parseComponent(content.trim(), {
|
|
83
81
|
pad: false,
|
|
@@ -89,7 +87,9 @@ describe('Single File Component parser', () => {
|
|
|
89
87
|
})
|
|
90
88
|
|
|
91
89
|
expect(deindentDefault.template!.content).toBe('\n<div></div>\n')
|
|
92
|
-
expect(deindentDefault.script!.content).toBe(
|
|
90
|
+
expect(deindentDefault.script!.content).toBe(
|
|
91
|
+
'\n export default {}\n '
|
|
92
|
+
)
|
|
93
93
|
expect(deindentDefault.styles[0].content).toBe('\nh1 { color: red }\n')
|
|
94
94
|
expect(deindentEnabled.template!.content).toBe('\n<div></div>\n')
|
|
95
95
|
expect(deindentEnabled.script!.content).toBe('\nexport default {}\n')
|
|
@@ -203,8 +203,7 @@ describe('Single File Component parser', () => {
|
|
|
203
203
|
}
|
|
204
204
|
</test>
|
|
205
205
|
<custom src="./x.json"></custom>
|
|
206
|
-
|
|
207
|
-
{ deindent: true }
|
|
206
|
+
`
|
|
208
207
|
)
|
|
209
208
|
expect(res.customBlocks.length).toBe(4)
|
|
210
209
|
|
|
@@ -3,6 +3,7 @@ import { getFirstComponentChild } from 'core/vdom/helpers/index'
|
|
|
3
3
|
import type VNode from 'core/vdom/vnode'
|
|
4
4
|
import type { VNodeComponentOptions } from 'types/vnode'
|
|
5
5
|
import type { Component } from 'types/component'
|
|
6
|
+
import { getComponentName } from '../vdom/create-component'
|
|
6
7
|
|
|
7
8
|
type CacheEntry = {
|
|
8
9
|
name?: string
|
|
@@ -12,8 +13,8 @@ type CacheEntry = {
|
|
|
12
13
|
|
|
13
14
|
type CacheEntryMap = Record<string, CacheEntry | null>
|
|
14
15
|
|
|
15
|
-
function
|
|
16
|
-
return opts && (opts.Ctor.options
|
|
16
|
+
function _getComponentName(opts?: VNodeComponentOptions): string | null {
|
|
17
|
+
return opts && (getComponentName(opts.Ctor.options as any) || opts.tag)
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
function matches(
|
|
@@ -81,7 +82,7 @@ export default {
|
|
|
81
82
|
if (vnodeToCache) {
|
|
82
83
|
const { tag, componentInstance, componentOptions } = vnodeToCache
|
|
83
84
|
cache[keyToCache] = {
|
|
84
|
-
name:
|
|
85
|
+
name: _getComponentName(componentOptions),
|
|
85
86
|
tag,
|
|
86
87
|
componentInstance
|
|
87
88
|
}
|
|
@@ -126,7 +127,7 @@ export default {
|
|
|
126
127
|
const componentOptions = vnode && vnode.componentOptions
|
|
127
128
|
if (componentOptions) {
|
|
128
129
|
// check pattern
|
|
129
|
-
const name =
|
|
130
|
+
const name = _getComponentName(componentOptions)
|
|
130
131
|
const { include, exclude } = this
|
|
131
132
|
if (
|
|
132
133
|
// not included
|
|
@@ -3,6 +3,7 @@ import type { Component } from 'types/component'
|
|
|
3
3
|
import type { GlobalAPI } from 'types/global-api'
|
|
4
4
|
import { defineComputed, proxy } from '../instance/state'
|
|
5
5
|
import { extend, mergeOptions, validateComponentName } from '../util/index'
|
|
6
|
+
import { getComponentName } from '../vdom/create-component'
|
|
6
7
|
|
|
7
8
|
export function initExtend(Vue: GlobalAPI) {
|
|
8
9
|
/**
|
|
@@ -25,7 +26,8 @@ export function initExtend(Vue: GlobalAPI) {
|
|
|
25
26
|
return cachedCtors[SuperId]
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
const name =
|
|
29
|
+
const name =
|
|
30
|
+
getComponentName(extendOptions) || getComponentName(Super.options)
|
|
29
31
|
if (__DEV__ && name) {
|
|
30
32
|
validateComponentName(name)
|
|
31
33
|
}
|
|
@@ -58,7 +58,7 @@ export function initMixin(Vue: typeof Component) {
|
|
|
58
58
|
initLifecycle(vm)
|
|
59
59
|
initEvents(vm)
|
|
60
60
|
initRender(vm)
|
|
61
|
-
callHook(vm, 'beforeCreate')
|
|
61
|
+
callHook(vm, 'beforeCreate', undefined, false /* setContext */)
|
|
62
62
|
initInjections(vm) // resolve injections before data/props
|
|
63
63
|
initState(vm)
|
|
64
64
|
initProvide(vm) // resolve provide after data/props
|
|
@@ -375,11 +375,16 @@ export function deactivateChildComponent(vm: Component, direct?: boolean) {
|
|
|
375
375
|
}
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
-
export function callHook(
|
|
378
|
+
export function callHook(
|
|
379
|
+
vm: Component,
|
|
380
|
+
hook: string,
|
|
381
|
+
args?: any[],
|
|
382
|
+
setContext = true
|
|
383
|
+
) {
|
|
379
384
|
// #7573 disable dep collection when invoking lifecycle hooks
|
|
380
385
|
pushTarget()
|
|
381
386
|
const prev = currentInstance
|
|
382
|
-
setCurrentInstance(vm)
|
|
387
|
+
setContext && setCurrentInstance(vm)
|
|
383
388
|
const handlers = vm.$options[hook]
|
|
384
389
|
const info = `${hook} hook`
|
|
385
390
|
if (handlers) {
|
|
@@ -390,6 +395,6 @@ export function callHook(vm: Component, hook: string, args?: any[]) {
|
|
|
390
395
|
if (vm._hasHookEvent) {
|
|
391
396
|
vm.$emit('hook:' + hook)
|
|
392
397
|
}
|
|
393
|
-
setCurrentInstance(prev)
|
|
398
|
+
setContext && setCurrentInstance(prev)
|
|
394
399
|
popTarget()
|
|
395
400
|
}
|
|
@@ -18,7 +18,7 @@ export function renderStatic(
|
|
|
18
18
|
// otherwise, render a fresh tree.
|
|
19
19
|
tree = cached[index] = this.$options.staticRenderFns[index].call(
|
|
20
20
|
this._renderProxy,
|
|
21
|
-
|
|
21
|
+
this._c,
|
|
22
22
|
this // for render fns generated for functional component templates
|
|
23
23
|
)
|
|
24
24
|
markStatic(tree, `__static__${index}`, false)
|
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
isUndef,
|
|
14
14
|
isValidArrayIndex,
|
|
15
15
|
isServerRendering,
|
|
16
|
-
hasChanged
|
|
16
|
+
hasChanged,
|
|
17
|
+
noop
|
|
17
18
|
} from '../util/index'
|
|
18
19
|
import { isReadonly, isRef, TrackOpTypes, TriggerOpTypes } from '../../v3'
|
|
19
20
|
|
|
@@ -31,6 +32,14 @@ export function toggleObserving(value: boolean) {
|
|
|
31
32
|
shouldObserve = value
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
// ssr mock dep
|
|
36
|
+
const mockDep = {
|
|
37
|
+
notify: noop,
|
|
38
|
+
depend: noop,
|
|
39
|
+
addSub: noop,
|
|
40
|
+
removeSub: noop
|
|
41
|
+
} as Dep
|
|
42
|
+
|
|
34
43
|
/**
|
|
35
44
|
* Observer class that is attached to each observed
|
|
36
45
|
* object. Once attached, the observer converts the target
|
|
@@ -41,78 +50,63 @@ export class Observer {
|
|
|
41
50
|
dep: Dep
|
|
42
51
|
vmCount: number // number of vms that have this object as root $data
|
|
43
52
|
|
|
44
|
-
constructor(public value: any, public shallow = false) {
|
|
53
|
+
constructor(public value: any, public shallow = false, public mock = false) {
|
|
45
54
|
// this.value = value
|
|
46
|
-
this.dep = new Dep()
|
|
55
|
+
this.dep = mock ? mockDep : new Dep()
|
|
47
56
|
this.vmCount = 0
|
|
48
57
|
def(value, '__ob__', this)
|
|
49
58
|
if (isArray(value)) {
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
if (!mock) {
|
|
60
|
+
if (hasProto) {
|
|
61
|
+
/* eslint-disable no-proto */
|
|
62
|
+
;(value as any).__proto__ = arrayMethods
|
|
63
|
+
/* eslint-enable no-proto */
|
|
64
|
+
} else {
|
|
65
|
+
for (let i = 0, l = arrayKeys.length; i < l; i++) {
|
|
66
|
+
const key = arrayKeys[i]
|
|
67
|
+
def(value, key, arrayMethods[key])
|
|
68
|
+
}
|
|
69
|
+
}
|
|
54
70
|
}
|
|
55
71
|
if (!shallow) {
|
|
56
72
|
this.observeArray(value)
|
|
57
73
|
}
|
|
58
74
|
} else {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const keys = Object.keys(obj)
|
|
70
|
-
for (let i = 0; i < keys.length; i++) {
|
|
71
|
-
const key = keys[i]
|
|
72
|
-
defineReactive(obj, key, NO_INIITIAL_VALUE, undefined, shallow)
|
|
75
|
+
/**
|
|
76
|
+
* Walk through all properties and convert them into
|
|
77
|
+
* getter/setters. This method should only be called when
|
|
78
|
+
* value type is Object.
|
|
79
|
+
*/
|
|
80
|
+
const keys = Object.keys(value)
|
|
81
|
+
for (let i = 0; i < keys.length; i++) {
|
|
82
|
+
const key = keys[i]
|
|
83
|
+
defineReactive(value, key, NO_INIITIAL_VALUE, undefined, shallow, mock)
|
|
84
|
+
}
|
|
73
85
|
}
|
|
74
86
|
}
|
|
75
87
|
|
|
76
88
|
/**
|
|
77
89
|
* Observe a list of Array items.
|
|
78
90
|
*/
|
|
79
|
-
observeArray(
|
|
80
|
-
for (let i = 0, l =
|
|
81
|
-
observe(
|
|
91
|
+
observeArray(value: any[]) {
|
|
92
|
+
for (let i = 0, l = value.length; i < l; i++) {
|
|
93
|
+
observe(value[i], false, this.mock)
|
|
82
94
|
}
|
|
83
95
|
}
|
|
84
96
|
}
|
|
85
97
|
|
|
86
98
|
// helpers
|
|
87
99
|
|
|
88
|
-
/**
|
|
89
|
-
* Augment a target Object or Array by intercepting
|
|
90
|
-
* the prototype chain using __proto__
|
|
91
|
-
*/
|
|
92
|
-
function protoAugment(target, src: Object) {
|
|
93
|
-
/* eslint-disable no-proto */
|
|
94
|
-
target.__proto__ = src
|
|
95
|
-
/* eslint-enable no-proto */
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Augment a target Object or Array by defining
|
|
100
|
-
* hidden properties.
|
|
101
|
-
*/
|
|
102
|
-
/* istanbul ignore next */
|
|
103
|
-
function copyAugment(target: Object, src: Object, keys: Array<string>) {
|
|
104
|
-
for (let i = 0, l = keys.length; i < l; i++) {
|
|
105
|
-
const key = keys[i]
|
|
106
|
-
def(target, key, src[key])
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
100
|
/**
|
|
111
101
|
* Attempt to create an observer instance for a value,
|
|
112
102
|
* returns the new observer if successfully observed,
|
|
113
103
|
* or the existing observer if the value already has one.
|
|
114
104
|
*/
|
|
115
|
-
export function observe(
|
|
105
|
+
export function observe(
|
|
106
|
+
value: any,
|
|
107
|
+
shallow?: boolean,
|
|
108
|
+
ssrMockReactivity?: boolean
|
|
109
|
+
): Observer | void {
|
|
116
110
|
if (!isObject(value) || isRef(value) || value instanceof VNode) {
|
|
117
111
|
return
|
|
118
112
|
}
|
|
@@ -121,12 +115,12 @@ export function observe(value: any, shallow?: boolean): Observer | void {
|
|
|
121
115
|
ob = value.__ob__
|
|
122
116
|
} else if (
|
|
123
117
|
shouldObserve &&
|
|
124
|
-
!isServerRendering() &&
|
|
118
|
+
(ssrMockReactivity || !isServerRendering()) &&
|
|
125
119
|
(isArray(value) || isPlainObject(value)) &&
|
|
126
120
|
Object.isExtensible(value) &&
|
|
127
|
-
!value.__v_skip
|
|
121
|
+
!value.__v_skip /* ReactiveFlags.SKIP */
|
|
128
122
|
) {
|
|
129
|
-
ob = new Observer(value, shallow)
|
|
123
|
+
ob = new Observer(value, shallow, ssrMockReactivity)
|
|
130
124
|
}
|
|
131
125
|
return ob
|
|
132
126
|
}
|
|
@@ -139,7 +133,8 @@ export function defineReactive(
|
|
|
139
133
|
key: string,
|
|
140
134
|
val?: any,
|
|
141
135
|
customSetter?: Function | null,
|
|
142
|
-
shallow?: boolean
|
|
136
|
+
shallow?: boolean,
|
|
137
|
+
mock?: boolean
|
|
143
138
|
) {
|
|
144
139
|
const dep = new Dep()
|
|
145
140
|
|
|
@@ -158,7 +153,7 @@ export function defineReactive(
|
|
|
158
153
|
val = obj[key]
|
|
159
154
|
}
|
|
160
155
|
|
|
161
|
-
let childOb = !shallow && observe(val)
|
|
156
|
+
let childOb = !shallow && observe(val, false, mock)
|
|
162
157
|
Object.defineProperty(obj, key, {
|
|
163
158
|
enumerable: true,
|
|
164
159
|
configurable: true,
|
|
@@ -202,7 +197,7 @@ export function defineReactive(
|
|
|
202
197
|
} else {
|
|
203
198
|
val = newVal
|
|
204
199
|
}
|
|
205
|
-
childOb = !shallow && observe(newVal)
|
|
200
|
+
childOb = !shallow && observe(newVal, false, mock)
|
|
206
201
|
if (__DEV__) {
|
|
207
202
|
dep.notify({
|
|
208
203
|
type: TriggerOpTypes.SET,
|
|
@@ -241,16 +236,20 @@ export function set(
|
|
|
241
236
|
__DEV__ && warn(`Set operation on key "${key}" failed: target is readonly.`)
|
|
242
237
|
return
|
|
243
238
|
}
|
|
239
|
+
const ob = (target as any).__ob__
|
|
244
240
|
if (isArray(target) && isValidArrayIndex(key)) {
|
|
245
241
|
target.length = Math.max(target.length, key)
|
|
246
242
|
target.splice(key, 1, val)
|
|
243
|
+
// when mocking for SSR, array methods are not hijacked
|
|
244
|
+
if (ob && !ob.shallow && ob.mock) {
|
|
245
|
+
observe(val, false, true)
|
|
246
|
+
}
|
|
247
247
|
return val
|
|
248
248
|
}
|
|
249
249
|
if (key in target && !(key in Object.prototype)) {
|
|
250
250
|
target[key] = val
|
|
251
251
|
return val
|
|
252
252
|
}
|
|
253
|
-
const ob = (target as any).__ob__
|
|
254
253
|
if ((target as any)._isVue || (ob && ob.vmCount)) {
|
|
255
254
|
__DEV__ &&
|
|
256
255
|
warn(
|
|
@@ -263,7 +262,7 @@ export function set(
|
|
|
263
262
|
target[key] = val
|
|
264
263
|
return val
|
|
265
264
|
}
|
|
266
|
-
defineReactive(ob.value, key, val)
|
|
265
|
+
defineReactive(ob.value, key, val, undefined, ob.shallow, ob.mock)
|
|
267
266
|
if (__DEV__) {
|
|
268
267
|
ob.dep.notify({
|
|
269
268
|
type: TriggerOpTypes.ADD,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { _Set as Set, isObject, isArray } from '../util/index'
|
|
2
2
|
import type { SimpleSet } from '../util/index'
|
|
3
3
|
import VNode from '../vdom/vnode'
|
|
4
|
+
import { isRef } from '../../v3'
|
|
4
5
|
|
|
5
6
|
const seenObjects = new Set()
|
|
6
7
|
|
|
@@ -35,6 +36,8 @@ function _traverse(val: any, seen: SimpleSet) {
|
|
|
35
36
|
if (isA) {
|
|
36
37
|
i = val.length
|
|
37
38
|
while (i--) _traverse(val[i], seen)
|
|
39
|
+
} else if (isRef(val)) {
|
|
40
|
+
_traverse(val.value, seen)
|
|
38
41
|
} else {
|
|
39
42
|
keys = Object.keys(val)
|
|
40
43
|
i = keys.length
|
package/src/core/util/debug.ts
CHANGED
|
@@ -2,6 +2,7 @@ import config from '../config'
|
|
|
2
2
|
import { noop, isArray, isFunction } from 'shared/util'
|
|
3
3
|
import type { Component } from 'types/component'
|
|
4
4
|
import { currentInstance } from 'v3/currentInstance'
|
|
5
|
+
import { getComponentName } from '../vdom/create-component'
|
|
5
6
|
|
|
6
7
|
export let warn: (msg: string, vm?: Component | null) => void = noop
|
|
7
8
|
export let tip = noop
|
|
@@ -40,7 +41,7 @@ if (__DEV__) {
|
|
|
40
41
|
: vm._isVue
|
|
41
42
|
? vm.$options || (vm.constructor as any).options
|
|
42
43
|
: vm
|
|
43
|
-
let name = options
|
|
44
|
+
let name = getComponentName(options)
|
|
44
45
|
const file = options.__file
|
|
45
46
|
if (!name && file) {
|
|
46
47
|
const match = file.match(/([^/\\]+)\.vue$/)
|
|
@@ -28,6 +28,10 @@ import type {
|
|
|
28
28
|
import type { Component } from 'types/component'
|
|
29
29
|
import type { ComponentOptions, InternalComponentOptions } from 'types/options'
|
|
30
30
|
|
|
31
|
+
export function getComponentName(options: ComponentOptions) {
|
|
32
|
+
return options.name || options.__name || options._componentTag
|
|
33
|
+
}
|
|
34
|
+
|
|
31
35
|
// inline hooks to be invoked on component VNodes during patch
|
|
32
36
|
const componentVNodeHooks = {
|
|
33
37
|
init(vnode: VNodeWithData, hydrating: boolean): boolean | void {
|
|
@@ -188,7 +192,7 @@ export function createComponent(
|
|
|
188
192
|
|
|
189
193
|
// return a placeholder vnode
|
|
190
194
|
// @ts-expect-error
|
|
191
|
-
const name = Ctor.options
|
|
195
|
+
const name = getComponentName(Ctor.options) || tag
|
|
192
196
|
const vnode = new VNode(
|
|
193
197
|
// @ts-expect-error
|
|
194
198
|
`vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from 'web/runtime/transition-util'
|
|
24
24
|
import VNode from 'core/vdom/vnode'
|
|
25
25
|
import { VNodeWithData } from 'types/vnode'
|
|
26
|
+
import { getComponentName } from 'core/vdom/create-component'
|
|
26
27
|
|
|
27
28
|
const props = extend(
|
|
28
29
|
{
|
|
@@ -72,7 +73,7 @@ export default {
|
|
|
72
73
|
} else if (__DEV__) {
|
|
73
74
|
const opts = c.componentOptions
|
|
74
75
|
const name: string = opts
|
|
75
|
-
? opts.Ctor.options
|
|
76
|
+
? getComponentName(opts.Ctor.options as any) || opts.tag || ''
|
|
76
77
|
: c.tag
|
|
77
78
|
warn(`<transition-group> children must be keyed: <${name}>`)
|
|
78
79
|
}
|
package/src/shared/constants.ts
CHANGED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { warn, isFunction, isObject } from 'core/util'
|
|
2
|
+
|
|
3
|
+
interface AsyncComponentOptions {
|
|
4
|
+
loader: Function
|
|
5
|
+
loadingComponent?: any
|
|
6
|
+
errorComponent?: any
|
|
7
|
+
delay?: number
|
|
8
|
+
timeout?: number
|
|
9
|
+
suspensible?: boolean
|
|
10
|
+
onError?: (
|
|
11
|
+
error: Error,
|
|
12
|
+
retry: () => void,
|
|
13
|
+
fail: () => void,
|
|
14
|
+
attempts: number
|
|
15
|
+
) => any
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type AsyncComponentFactory = () => {
|
|
19
|
+
component: Promise<any>
|
|
20
|
+
loading?: any
|
|
21
|
+
error?: any
|
|
22
|
+
delay?: number
|
|
23
|
+
timeout?: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* v3-compatible async component API.
|
|
28
|
+
* @internal the type is manually declared in <root>/types/v3-define-async-component.d.ts
|
|
29
|
+
* because it relies on existing manual types
|
|
30
|
+
*/
|
|
31
|
+
export function defineAsyncComponent(
|
|
32
|
+
source: (() => any) | AsyncComponentOptions
|
|
33
|
+
): AsyncComponentFactory {
|
|
34
|
+
if (isFunction(source)) {
|
|
35
|
+
source = { loader: source } as AsyncComponentOptions
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const {
|
|
39
|
+
loader,
|
|
40
|
+
loadingComponent,
|
|
41
|
+
errorComponent,
|
|
42
|
+
delay = 200,
|
|
43
|
+
timeout, // undefined = never times out
|
|
44
|
+
suspensible = false, // in Vue 3 default is true
|
|
45
|
+
onError: userOnError
|
|
46
|
+
} = source
|
|
47
|
+
|
|
48
|
+
if (__DEV__ && suspensible) {
|
|
49
|
+
warn(
|
|
50
|
+
`The suspensiblbe option for async components is not supported in Vue2. It is ignored.`
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let pendingRequest: Promise<any> | null = null
|
|
55
|
+
|
|
56
|
+
let retries = 0
|
|
57
|
+
const retry = () => {
|
|
58
|
+
retries++
|
|
59
|
+
pendingRequest = null
|
|
60
|
+
return load()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const load = (): Promise<any> => {
|
|
64
|
+
let thisRequest: Promise<any>
|
|
65
|
+
return (
|
|
66
|
+
pendingRequest ||
|
|
67
|
+
(thisRequest = pendingRequest =
|
|
68
|
+
loader()
|
|
69
|
+
.catch(err => {
|
|
70
|
+
err = err instanceof Error ? err : new Error(String(err))
|
|
71
|
+
if (userOnError) {
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
const userRetry = () => resolve(retry())
|
|
74
|
+
const userFail = () => reject(err)
|
|
75
|
+
userOnError(err, userRetry, userFail, retries + 1)
|
|
76
|
+
})
|
|
77
|
+
} else {
|
|
78
|
+
throw err
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
.then((comp: any) => {
|
|
82
|
+
if (thisRequest !== pendingRequest && pendingRequest) {
|
|
83
|
+
return pendingRequest
|
|
84
|
+
}
|
|
85
|
+
if (__DEV__ && !comp) {
|
|
86
|
+
warn(
|
|
87
|
+
`Async component loader resolved to undefined. ` +
|
|
88
|
+
`If you are using retry(), make sure to return its return value.`
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
// interop module default
|
|
92
|
+
if (
|
|
93
|
+
comp &&
|
|
94
|
+
(comp.__esModule || comp[Symbol.toStringTag] === 'Module')
|
|
95
|
+
) {
|
|
96
|
+
comp = comp.default
|
|
97
|
+
}
|
|
98
|
+
if (__DEV__ && comp && !isObject(comp) && !isFunction(comp)) {
|
|
99
|
+
throw new Error(`Invalid async component load result: ${comp}`)
|
|
100
|
+
}
|
|
101
|
+
return comp
|
|
102
|
+
}))
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return () => {
|
|
107
|
+
const component = load()
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
component,
|
|
111
|
+
delay,
|
|
112
|
+
timeout,
|
|
113
|
+
error: errorComponent,
|
|
114
|
+
loading: loadingComponent
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
package/src/v3/apiWatch.ts
CHANGED
|
@@ -196,12 +196,10 @@ function doWatch(
|
|
|
196
196
|
getter = () => source.value
|
|
197
197
|
forceTrigger = isShallow(source)
|
|
198
198
|
} else if (isReactive(source)) {
|
|
199
|
-
getter =
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
: () => source
|
|
199
|
+
getter = () => {
|
|
200
|
+
;(source as any).__ob__.dep.depend()
|
|
201
|
+
return source
|
|
202
|
+
}
|
|
205
203
|
deep = true
|
|
206
204
|
} else if (isArray(source)) {
|
|
207
205
|
isMultiSource = true
|
|
@@ -320,8 +318,8 @@ function doWatch(
|
|
|
320
318
|
} else {
|
|
321
319
|
// pre
|
|
322
320
|
watcher.update = () => {
|
|
323
|
-
if (instance && instance === currentInstance) {
|
|
324
|
-
// pre-watcher triggered
|
|
321
|
+
if (instance && instance === currentInstance && !instance._isMounted) {
|
|
322
|
+
// pre-watcher triggered before
|
|
325
323
|
const buffer = instance._preWatchers || (instance._preWatchers = [])
|
|
326
324
|
if (buffer.indexOf(watcher) < 0) buffer.push(watcher)
|
|
327
325
|
} else {
|
package/src/v3/index.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Note: also update dist/vue.runtime.mjs when adding new exports to this file.
|
|
3
|
+
*/
|
|
4
|
+
|
|
1
5
|
export const version: string = '__VERSION__'
|
|
2
6
|
|
|
3
7
|
export {
|
|
@@ -87,4 +91,6 @@ export function defineComponent(options: any) {
|
|
|
87
91
|
return options
|
|
88
92
|
}
|
|
89
93
|
|
|
94
|
+
export { defineAsyncComponent } from './apiAsyncComponent'
|
|
95
|
+
|
|
90
96
|
export * from './apiLifecycle'
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { observe, Observer } from 'core/observer'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
def,
|
|
4
|
+
isArray,
|
|
5
|
+
isPrimitive,
|
|
6
|
+
warn,
|
|
7
|
+
toRawType,
|
|
8
|
+
isServerRendering
|
|
9
|
+
} from 'core/util'
|
|
3
10
|
import type { Ref, UnwrapRefSimple, RawSymbol } from './ref'
|
|
4
11
|
|
|
5
12
|
export const enum ReactiveFlags {
|
|
@@ -67,7 +74,11 @@ function makeReactive(target: any, shallow: boolean) {
|
|
|
67
74
|
)
|
|
68
75
|
}
|
|
69
76
|
}
|
|
70
|
-
const ob = observe(
|
|
77
|
+
const ob = observe(
|
|
78
|
+
target,
|
|
79
|
+
shallow,
|
|
80
|
+
isServerRendering() /* ssr mock reactivity */
|
|
81
|
+
)
|
|
71
82
|
if (__DEV__ && !ob) {
|
|
72
83
|
if (target == null || isPrimitive(target)) {
|
|
73
84
|
warn(`value cannot be made reactive: ${String(target)}`)
|