Skip to content

Commit 86a714c

Browse files
committed
refactor create-component.js
1 parent 92e9192 commit 86a714c

File tree

5 files changed

+149
-119
lines changed

5 files changed

+149
-119
lines changed

Diff for: src/core/vdom/create-component.js

+7-116
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ import { resolveConstructorOptions } from '../instance/init'
66
import { resolveSlots } from '../instance/render-helpers/resolve-slots'
77

88
import {
9-
tip,
109
warn,
1110
isObject,
12-
hasOwn,
13-
hyphenate,
14-
validateProp,
15-
formatComponentName
11+
validateProp
1612
} from '../util/index'
1713

14+
import {
15+
resolveAsyncComponent,
16+
extractPropsFromVNodeData
17+
} from './helpers/index'
18+
1819
import {
1920
callHook,
2021
activeInstance,
@@ -134,7 +135,7 @@ export function createComponent (
134135
}
135136

136137
// extract props
137-
const propsData = extractProps(data, Ctor, tag)
138+
const propsData = extractPropsFromVNodeData(data, Ctor, tag)
138139

139140
// functional component
140141
if (Ctor.options.functional) {
@@ -227,116 +228,6 @@ export function createComponentInstanceForVnode (
227228
return new vnodeComponentOptions.Ctor(options)
228229
}
229230

230-
function resolveAsyncComponent (
231-
factory: Function,
232-
baseCtor: Class<Component>,
233-
cb: Function
234-
): Class<Component> | void {
235-
if (factory.requested) {
236-
// pool callbacks
237-
factory.pendingCallbacks.push(cb)
238-
} else {
239-
factory.requested = true
240-
const cbs = factory.pendingCallbacks = [cb]
241-
let sync = true
242-
243-
const resolve = (res: Object | Class<Component>) => {
244-
if (isObject(res)) {
245-
res = baseCtor.extend(res)
246-
}
247-
// cache resolved
248-
factory.resolved = res
249-
// invoke callbacks only if this is not a synchronous resolve
250-
// (async resolves are shimmed as synchronous during SSR)
251-
if (!sync) {
252-
for (let i = 0, l = cbs.length; i < l; i++) {
253-
cbs[i](res)
254-
}
255-
}
256-
}
257-
258-
const reject = reason => {
259-
process.env.NODE_ENV !== 'production' && warn(
260-
`Failed to resolve async component: ${String(factory)}` +
261-
(reason ? `\nReason: ${reason}` : '')
262-
)
263-
}
264-
265-
const res = factory(resolve, reject)
266-
267-
// handle promise
268-
if (res && typeof res.then === 'function' && !factory.resolved) {
269-
res.then(resolve, reject)
270-
}
271-
272-
sync = false
273-
// return in case resolved synchronously
274-
return factory.resolved
275-
}
276-
}
277-
278-
function extractProps (data: VNodeData, Ctor: Class<Component>, tag?: string): ?Object {
279-
// we are only extracting raw values here.
280-
// validation and default values are handled in the child
281-
// component itself.
282-
const propOptions = Ctor.options.props
283-
if (!propOptions) {
284-
return
285-
}
286-
const res = {}
287-
const { attrs, props, domProps } = data
288-
if (attrs || props || domProps) {
289-
for (const key in propOptions) {
290-
const altKey = hyphenate(key)
291-
if (process.env.NODE_ENV !== 'production') {
292-
const keyInLowerCase = key.toLowerCase()
293-
if (
294-
key !== keyInLowerCase &&
295-
attrs && attrs.hasOwnProperty(keyInLowerCase)
296-
) {
297-
tip(
298-
`Prop "${keyInLowerCase}" is passed to component ` +
299-
`${formatComponentName(tag || Ctor)}, but the declared prop name is` +
300-
` "${key}". ` +
301-
`Note that HTML attributes are case-insensitive and camelCased ` +
302-
`props need to use their kebab-case equivalents when using in-DOM ` +
303-
`templates. You should probably use "${altKey}" instead of "${key}".`
304-
)
305-
}
306-
}
307-
checkProp(res, props, key, altKey, true) ||
308-
checkProp(res, attrs, key, altKey) ||
309-
checkProp(res, domProps, key, altKey)
310-
}
311-
}
312-
return res
313-
}
314-
315-
function checkProp (
316-
res: Object,
317-
hash: ?Object,
318-
key: string,
319-
altKey: string,
320-
preserve?: boolean
321-
): boolean {
322-
if (hash) {
323-
if (hasOwn(hash, key)) {
324-
res[key] = hash[key]
325-
if (!preserve) {
326-
delete hash[key]
327-
}
328-
return true
329-
} else if (hasOwn(hash, altKey)) {
330-
res[key] = hash[altKey]
331-
if (!preserve) {
332-
delete hash[altKey]
333-
}
334-
return true
335-
}
336-
}
337-
return false
338-
}
339-
340231
function mergeHooks (data: VNodeData) {
341232
if (!data.hook) {
342233
data.hook = {}

Diff for: src/core/vdom/create-element.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
/* @flow */
22

3-
import VNode, { createEmptyVNode } from './vnode'
43
import config from '../config'
4+
import VNode, { createEmptyVNode } from './vnode'
55
import { createComponent } from './create-component'
6-
import { normalizeChildren, simpleNormalizeChildren } from './helpers/index'
7-
import { warn, resolveAsset, isPrimitive } from '../util/index'
6+
7+
import {
8+
warn,
9+
resolveAsset,
10+
isPrimitive
11+
} from '../util/index'
12+
13+
import {
14+
normalizeChildren,
15+
simpleNormalizeChildren
16+
} from './helpers/index'
817

918
const SIMPLE_NORMALIZE = 1
1019
const ALWAYS_NORMALIZE = 2

Diff for: src/core/vdom/helpers/extract-props.js

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/* @flow */
2+
3+
import {
4+
tip,
5+
hasOwn,
6+
hyphenate,
7+
formatComponentName
8+
} from 'core/util/index'
9+
10+
export function extractPropsFromVNodeData (
11+
data: VNodeData,
12+
Ctor: Class<Component>,
13+
tag?: string
14+
): ?Object {
15+
// we are only extracting raw values here.
16+
// validation and default values are handled in the child
17+
// component itself.
18+
const propOptions = Ctor.options.props
19+
if (!propOptions) {
20+
return
21+
}
22+
const res = {}
23+
const { attrs, props, domProps } = data
24+
if (attrs || props || domProps) {
25+
for (const key in propOptions) {
26+
const altKey = hyphenate(key)
27+
if (process.env.NODE_ENV !== 'production') {
28+
const keyInLowerCase = key.toLowerCase()
29+
if (
30+
key !== keyInLowerCase &&
31+
attrs && attrs.hasOwnProperty(keyInLowerCase)
32+
) {
33+
tip(
34+
`Prop "${keyInLowerCase}" is passed to component ` +
35+
`${formatComponentName(tag || Ctor)}, but the declared prop name is` +
36+
` "${key}". ` +
37+
`Note that HTML attributes are case-insensitive and camelCased ` +
38+
`props need to use their kebab-case equivalents when using in-DOM ` +
39+
`templates. You should probably use "${altKey}" instead of "${key}".`
40+
)
41+
}
42+
}
43+
checkProp(res, props, key, altKey, true) ||
44+
checkProp(res, attrs, key, altKey) ||
45+
checkProp(res, domProps, key, altKey)
46+
}
47+
}
48+
return res
49+
}
50+
51+
function checkProp (
52+
res: Object,
53+
hash: ?Object,
54+
key: string,
55+
altKey: string,
56+
preserve?: boolean
57+
): boolean {
58+
if (hash) {
59+
if (hasOwn(hash, key)) {
60+
res[key] = hash[key]
61+
if (!preserve) {
62+
delete hash[key]
63+
}
64+
return true
65+
} else if (hasOwn(hash, altKey)) {
66+
res[key] = hash[altKey]
67+
if (!preserve) {
68+
delete hash[altKey]
69+
}
70+
return true
71+
}
72+
}
73+
return false
74+
}

Diff for: src/core/vdom/helpers/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
/* @flow */
22

33
export * from './merge-hook'
4+
export * from './extract-props'
45
export * from './update-listeners'
56
export * from './normalize-children'
7+
export * from './resolve-async-component'
68

79
export function getFirstComponentChild (children: ?Array<VNode>): ?VNode {
810
return children && children.filter((c: VNode) => c && c.componentOptions)[0]

Diff for: src/core/vdom/helpers/resolve-async-component.js

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* @flow */
2+
3+
import {
4+
warn,
5+
isObject
6+
} from 'core/util/index'
7+
8+
export function resolveAsyncComponent (
9+
factory: Function,
10+
baseCtor: Class<Component>,
11+
cb: Function
12+
): Class<Component> | void {
13+
if (factory.requested) {
14+
// pool callbacks
15+
factory.pendingCallbacks.push(cb)
16+
} else {
17+
factory.requested = true
18+
const cbs = factory.pendingCallbacks = [cb]
19+
let sync = true
20+
21+
const resolve = (res: Object | Class<Component>) => {
22+
if (isObject(res)) {
23+
res = baseCtor.extend(res)
24+
}
25+
// cache resolved
26+
factory.resolved = res
27+
// invoke callbacks only if this is not a synchronous resolve
28+
// (async resolves are shimmed as synchronous during SSR)
29+
if (!sync) {
30+
for (let i = 0, l = cbs.length; i < l; i++) {
31+
cbs[i](res)
32+
}
33+
}
34+
}
35+
36+
const reject = reason => {
37+
process.env.NODE_ENV !== 'production' && warn(
38+
`Failed to resolve async component: ${String(factory)}` +
39+
(reason ? `\nReason: ${reason}` : '')
40+
)
41+
}
42+
43+
const res = factory(resolve, reject)
44+
45+
// handle promise
46+
if (res && typeof res.then === 'function' && !factory.resolved) {
47+
res.then(resolve, reject)
48+
}
49+
50+
sync = false
51+
// return in case resolved synchronously
52+
return factory.resolved
53+
}
54+
}

0 commit comments

Comments
 (0)