@@ -2,36 +2,89 @@ import Vue from 'vue'
2
2
import layoutComponents from '@internal/layout-components'
3
3
import pageComponents from '@internal/page-components'
4
4
5
- const asyncComponents = Object . assign ( { } , layoutComponents , pageComponents )
6
-
7
- export function isPageExists ( pageKey ) {
8
- return Boolean ( pageComponents [ pageKey ] )
5
+ /**
6
+ * Create a cached version of a pure function.
7
+ */
8
+ function cached ( fn ) {
9
+ const cache = Object . create ( null )
10
+ // eslint-disable-next-line func-names
11
+ return function cachedFn ( str ) {
12
+ const hit = cache [ str ]
13
+ // eslint-disable-next-line no-return-assign
14
+ return hit || ( cache [ str ] = fn ( str ) )
15
+ }
9
16
}
10
17
11
- export function isPageLoaded ( pageKey ) {
12
- return Boolean ( Vue . component ( pageKey ) )
18
+ /**
19
+ * Camelize a hyphen-delimited string.
20
+ */
21
+ const camelizeRE = / - ( \w ) / g
22
+ const camelize = cached ( str => {
23
+ return str . replace ( camelizeRE , ( _ , c ) => c ? c . toUpperCase ( ) : '' )
24
+ } )
25
+
26
+ /**
27
+ * Hyphenate a camelCase string.
28
+ */
29
+ const hyphenateRE = / \B ( [ A - Z ] ) / g
30
+ const hyphenate = cached ( str => {
31
+ return str . replace ( hyphenateRE , '-$1' ) . toLowerCase ( )
32
+ } )
33
+
34
+ /**
35
+ * Capitalize a string.
36
+ */
37
+ const capitalize = cached ( str => {
38
+ return str . charAt ( 0 ) . toUpperCase ( ) + str . slice ( 1 )
39
+ } )
40
+
41
+ /**
42
+ * This method was for securely getting Vue component when components
43
+ * are named in different style.
44
+ *
45
+ * e.g. a component named `a-b` can be also getted by `AB`, It's the
46
+ * same the other way round
47
+ *
48
+ * @param {function } getter a function of getting component by name
49
+ * @param {string } name component's name
50
+ * @returns {Component|AsyncComponent }
51
+ */
52
+ export function getComponent ( getter , name ) {
53
+ if ( ! name ) return
54
+ if ( getter ( name ) ) return getter ( name )
55
+
56
+ const isKebabCase = name . includes ( '-' )
57
+ if ( isKebabCase ) return getter ( capitalize ( camelize ( name ) ) )
58
+
59
+ return getter ( capitalize ( name ) ) || getter ( hyphenate ( name ) )
13
60
}
14
61
62
+ const asyncComponents = Object . assign ( { } , layoutComponents , pageComponents )
63
+ const asyncComponentsGetter = name => asyncComponents [ name ]
64
+ const pageComponentsGetter = layout => pageComponents [ layout ]
65
+ const layoutComponentsGetter = layout => layoutComponents [ layout ]
66
+ const globalComponentsGetter = name => Vue . component ( name )
67
+
15
68
export function getPageAsyncComponent ( pageKey ) {
16
- return pageComponents [ pageKey ]
69
+ return getComponent ( pageComponentsGetter , pageKey )
17
70
}
18
71
19
- export function isLayoutExists ( layout ) {
20
- return Boolean ( layoutComponents [ layout ] )
72
+ export function getLayoutAsyncComponent ( layout ) {
73
+ return getComponent ( layoutComponentsGetter , layout )
21
74
}
22
75
23
- export function isLayoutLoaded ( layout ) {
24
- return Boolean ( Vue . component ( layout ) )
76
+ export function getAsyncComponent ( name ) {
77
+ return getComponent ( asyncComponentsGetter , name )
25
78
}
26
79
27
- export function getLayoutAsyncComponent ( pageKey ) {
28
- return layoutComponents [ pageKey ]
80
+ export function getVueComponent ( name ) {
81
+ return getComponent ( globalComponentsGetter , name )
29
82
}
30
83
31
84
export function ensureAsyncComponentsLoaded ( ...names ) {
32
85
return Promise . all ( names . filter ( v => v ) . map ( async ( name ) => {
33
- if ( ! Vue . component ( name ) && asyncComponents [ name ] ) {
34
- const comp = await asyncComponents [ name ] ( )
86
+ if ( ! getVueComponent ( name ) && getAsyncComponent ( name ) ) {
87
+ const comp = await getAsyncComponent ( name ) ( )
35
88
Vue . component ( name , comp . default )
36
89
}
37
90
} ) )
0 commit comments