1
1
import { defineComponent } from 'vue' ;
2
- import { obtainSlot , toBaseReverse } from './utils'
2
+ import { obtainSlot , extendSlotPath } from './utils'
3
3
import { build as optionComputed } from './option/computed'
4
4
import { build as optionData } from './option/data'
5
5
import { build as optionMethodsAndLifecycle } from './option/methodsAndLifecycle'
@@ -20,7 +20,7 @@ export interface OptionBuilder {
20
20
21
21
}
22
22
export interface Cons { new ( ) : any , prototype : any }
23
- function ComponentOption ( cons : Cons ) {
23
+ function ComponentOption ( cons : Cons , extend ?: any ) {
24
24
const optionBuilder : OptionBuilder = { }
25
25
optionComputed ( cons , optionBuilder )
26
26
optionWatch ( cons , optionBuilder )
@@ -41,12 +41,13 @@ function ComponentOption(cons: Cons) {
41
41
watch : optionBuilder . watch ,
42
42
props : optionBuilder . props ,
43
43
inject : optionBuilder . inject ,
44
- ...optionBuilder . lifecycle
44
+ ...optionBuilder . lifecycle ,
45
+ extends : extend
45
46
}
46
47
return raw as any
47
48
}
48
49
49
- export function Component ( arg : Cons | {
50
+ type ComponentOption = {
50
51
name ?: string
51
52
emits ?: string [ ]
52
53
provide ?: Record < string , any > | Function
@@ -55,43 +56,92 @@ export function Component(arg: Cons | {
55
56
inheritAttrs ?: boolean ;
56
57
expose ?: string [ ] ;
57
58
modifier ?: ( raw : any ) => any
58
- } ) : any {
59
- if ( typeof arg === 'function' ) {
60
- return defineComponent ( ComponentOption ( arg ) )
59
+ }
60
+ type ComponentConsOption = Cons | ComponentOption
61
+ function ComponentStep ( cons : Cons , extend ?: any ) {
62
+ return defineComponent ( ComponentOption ( cons , extend ) )
63
+ }
64
+
65
+ function ComponentStepWithOption ( cons : Cons , arg : ComponentOption , extend ?: any ) : any {
66
+ let option = ComponentOption ( cons , extend )
67
+ const slot = obtainSlot ( cons . prototype )
68
+ if ( typeof arg . name !== 'undefined' ) {
69
+ option . name = arg . name
61
70
}
62
- return function ( cons : Cons ) {
63
- let option = ComponentOption ( cons )
64
- const slot = obtainSlot ( cons . prototype )
65
- if ( typeof arg . name !== 'undefined' ) {
66
- option . name = arg . name
67
- }
68
71
69
- let emits = Array . from ( slot . obtainMap ( 'emits' ) . keys ( ) )
70
- if ( Array . isArray ( arg . emits ) ) {
71
- emits = Array . from ( new Set ( [ ...emits , ...arg . emits ] ) )
72
- }
73
- option . emits = emits
72
+ let emits = Array . from ( slot . obtainMap ( 'emits' ) . keys ( ) )
73
+ if ( Array . isArray ( arg . emits ) ) {
74
+ emits = Array . from ( new Set ( [ ...emits , ...arg . emits ] ) )
75
+ }
76
+ option . emits = emits
74
77
75
78
76
- if ( arg . components ) {
77
- option . components = arg . components
78
- }
79
- if ( arg . provide ) {
80
- option . provide = arg . provide
81
- }
82
- if ( arg . directives ) {
83
- option . directives = arg . directives
84
- }
85
- if ( arg . inheritAttrs ) {
86
- option . inheritAttrs = arg . inheritAttrs
87
- }
88
- if ( arg . expose ) {
89
- option . expose = arg . expose
90
- }
91
- if ( arg . modifier ) {
92
- option = arg . modifier ( option )
79
+ if ( arg . components ) {
80
+ option . components = arg . components
81
+ }
82
+ if ( arg . provide ) {
83
+ option . provide = arg . provide
84
+ }
85
+ if ( arg . directives ) {
86
+ option . directives = arg . directives
87
+ }
88
+ if ( arg . inheritAttrs ) {
89
+ option . inheritAttrs = arg . inheritAttrs
90
+ }
91
+ if ( arg . expose ) {
92
+ option . expose = arg . expose
93
+ }
94
+
95
+ if ( arg . modifier ) {
96
+ option = arg . modifier ( option )
97
+ if ( ! option ) {
98
+ throw 'Component modifier should return vue component option'
93
99
}
100
+ }
101
+ return defineComponent ( option )
102
+ }
103
+
104
+ export function ComponentBase ( cons : Cons ) {
105
+ const slot = obtainSlot ( cons . prototype )
106
+ slot . inComponent = true
107
+ return cons
108
+ }
109
+
110
+ export function Component ( arg : Cons | ComponentOption ) {
111
+
112
+ function extend ( cons : Cons ) {
113
+ ComponentBase ( cons )
114
+ const slotPath = extendSlotPath ( cons . prototype )
115
+
116
+ slotPath . forEach ( proto => {
117
+ const slot = obtainSlot ( proto )
118
+ if ( ! slot . inComponent ) {
119
+ throw 'Class should be decorated by Component or ComponentBase: ' + proto . constructor
120
+ }
121
+ } )
122
+
123
+ return slotPath . reduceRight < any > ( ( pv , cv , ci ) => {
124
+ if ( ci > 0 ) {
125
+ return ComponentStep ( cv . constructor , pv === null ? undefined : pv )
126
+ } else {
127
+
128
+ if ( typeof arg === 'function' ) {
129
+ return ComponentStepWithOption ( cv . constructor , { } , pv === null ? undefined : pv )
130
+ } else {
131
+ return ComponentStepWithOption ( cv . constructor , arg , pv === null ? undefined : pv )
132
+ }
133
+ }
134
+ } , null )
135
+ }
136
+ if ( typeof arg === 'function' ) {
137
+
138
+ const finalComp = extend ( arg )
139
+ return finalComp
140
+ }
141
+ return function ( cons : Cons ) {
142
+
143
+ const finalComp = extend ( cons )
94
144
95
- return defineComponent ( option )
145
+ return finalComp
96
146
}
97
147
}
0 commit comments