1
- import { watch } from 'vue' ;
2
- import { getCurrentInstance , type VueInstance , isVue2 , isVue3 } from './vue' ;
1
+ import { getCurrentInstance , type VueInstance , isVue2 } from './vue' ;
3
2
import { setupReference } from './setup-reference' ;
4
3
import { TargetName , Target } from './types' ;
5
4
import {
9
8
} from './config' ;
10
9
import { createDefineProperty } from './property-descriptors' ;
11
10
import { DefineConstructor } from './define' ;
12
- import { SETUP_SETUP_DEFINE } from './config' ;
11
+ import { SETUP_SETUP_DEFINE , SETUP_USE } from './config' ;
13
12
14
13
let currentTarget : Target | null = null ;
15
14
let currentName : TargetName | null = null ;
@@ -28,43 +27,50 @@ export function setCurrentHookName(name: TargetName | null) {
28
27
currentName = name ;
29
28
}
30
29
31
- function initProps ( target : VueInstance , app : InstanceType < DefineConstructor > ) {
32
- const keys = Object . keys ( app . $defaultProps || { } ) ;
33
- if ( keys . length ) {
34
- watch (
35
- ( ) => {
36
- const props = target [ '$props' ] ;
37
- if ( ! props ) return { } ;
38
- const data : Record < string , any > = { } ;
39
- keys . forEach ( ( key ) => {
40
- if ( props [ key ] !== app [ key ] ) {
41
- data [ key ] = app [ key ] ;
42
- }
43
- } ) ;
44
- return data ;
30
+ function use ( target : VueInstance , _This : any ) {
31
+ let use : Map < any , InstanceType < DefineConstructor > > ;
32
+ if ( target [ SETUP_USE ] ) {
33
+ use = target [ SETUP_USE ] ;
34
+ } else {
35
+ use = new Map ( ) ;
36
+ target [ SETUP_USE ] = use ;
37
+ }
38
+ let app = use . get ( _This ) ! ;
39
+ if ( app ) {
40
+ return app ;
41
+ }
42
+ app = new _This ( ) as InstanceType < DefineConstructor > ;
43
+
44
+ use . set ( _This , app ) ;
45
+
46
+ const names = Object . getOwnPropertyNames ( app ) ;
47
+ const defineProperty = createDefineProperty ( target ) ;
48
+ const propertyDescriptor = _This [ SETUP_PROPERTY_DESCRIPTOR ] as Map <
49
+ string ,
50
+ PropertyDescriptor
51
+ > ;
52
+ names . forEach ( ( name ) => {
53
+ if ( propertyDescriptor . has ( name ) || name === SETUP_SETUP_DEFINE ) return ;
54
+ defineProperty ( name , {
55
+ get ( ) {
56
+ return app [ name ] ;
45
57
} ,
46
- ( defaultProps ) => {
47
- const props = target [ '$props' ] ;
48
- if ( ! props ) {
49
- return ;
50
- }
51
- const definePropertyProps = createDefineProperty ( props ) ;
52
- Object . keys ( defaultProps ) . forEach ( ( key ) => {
53
- const descriptor = Object . getOwnPropertyDescriptor (
54
- props ,
55
- key
56
- ) ;
57
- definePropertyProps ( key , {
58
- ...descriptor ,
59
- value : defaultProps [ key ] ,
60
- } ) ;
61
- } ) ;
58
+ set ( val ) {
59
+ app [ name ] = val ;
62
60
} ,
63
- {
64
- immediate : true ,
65
- }
66
- ) ;
67
- }
61
+ } ) ;
62
+ } ) ;
63
+ propertyDescriptor . forEach ( ( value , name ) => {
64
+ defineProperty ( name , {
65
+ get ( ) {
66
+ return app [ name ] ;
67
+ } ,
68
+ set ( val ) {
69
+ app [ name ] = val ;
70
+ } ,
71
+ } ) ;
72
+ } ) ;
73
+ return app ;
68
74
}
69
75
70
76
export class Context {
@@ -74,75 +80,46 @@ export class Context {
74
80
string ,
75
81
PropertyDescriptor
76
82
> ( ) ;
83
+ public static use < T extends new ( ...args : any ) => any > ( this : T ) {
84
+ const vm = getCurrentInstance ( ) ;
85
+ if ( ! vm ) {
86
+ throw Error ( 'Please run in the setup function' ) ;
87
+ }
88
+ return use ( vm , this ) as InstanceType < T > ;
89
+ }
77
90
public static inject < T extends new ( ...args : any ) => any > ( this : T ) {
78
91
const _This = this ;
79
- const map = _This [ SETUP_PROPERTY_DESCRIPTOR ] as Map <
80
- string ,
81
- PropertyDescriptor
82
- > ;
83
- function use ( target : VueInstance ) {
84
- const app = new _This ( ) as InstanceType < DefineConstructor > ;
85
- const names = Object . getOwnPropertyNames ( app ) ;
86
- const defineProperty = createDefineProperty ( target ) ;
87
- // Watch default props
88
- if ( isVue3 ) {
89
- initProps ( target , app ) ;
90
- }
91
92
92
- names . forEach ( ( name ) => {
93
- if ( map . has ( name ) ) return ;
94
- defineProperty ( name , {
95
- get ( ) {
96
- return app [ name ] ;
97
- } ,
98
- set ( val ) {
99
- app [ name ] = val ;
100
- } ,
101
- } ) ;
102
- } ) ;
103
- map . forEach ( ( value , name ) => {
104
- defineProperty ( name , {
105
- get ( ) {
106
- return app [ name ] ;
107
- } ,
108
- set ( val ) {
109
- app [ name ] = val ;
110
- } ,
111
- } ) ;
112
- } ) ;
113
- return app as InstanceType < T > ;
114
- }
115
- const data : {
116
- beforeCreate ?: ( ) => void ;
117
- created ?: ( ) => void ;
118
- setup : ( ) => InstanceType < T > ;
119
- } = {
93
+ return {
120
94
setup ( ) {
121
95
return { } as InstanceType < T > ;
122
96
} ,
123
- } ;
124
- if ( isVue2 ) {
125
- data . beforeCreate = function beforeCreate ( ) {
126
- const vm = this as any ;
127
- if ( ! vm . $options ) return ;
128
- const setup = vm . $options . setup ;
129
- vm . $options . setup = ( props : any , ctx : any ) => {
130
- const app = use ( vm ) as any ;
131
- if ( app [ SETUP_SETUP_DEFINE ] ) {
132
- return setup ( app , ctx ) ;
133
- }
134
- if ( setup ) {
135
- return setup ( props , ctx ) ;
97
+ created ( ) {
98
+ const vm = this as any as VueInstance ;
99
+ const app = use ( vm , _This ) ;
100
+ if ( ! vm . $options || isVue2 ) {
101
+ return ;
102
+ }
103
+ const render = vm . $options . render as Function | undefined ;
104
+ if ( app [ SETUP_SETUP_DEFINE ] && render ) {
105
+ const proxyRender = ( ...args : any [ ] ) => {
106
+ const props = vm . $ . props ;
107
+ for ( let i = 0 ; i < args . length ; i ++ ) {
108
+ if ( args [ i ] === props ) {
109
+ args [ i ] = app ;
110
+ break ;
111
+ }
112
+ }
113
+ return render . apply ( this , args ) ;
114
+ } ;
115
+ vm . $options . render = proxyRender ;
116
+
117
+ if ( vm . $ ) {
118
+ ( vm as any ) . $ . render = proxyRender ;
136
119
}
137
- return { } ;
138
- } ;
139
- } ;
140
- } else {
141
- data . created = function created ( ) {
142
- use ( this as any ) ;
143
- } ;
144
- }
145
- return data ;
120
+ }
121
+ } ,
122
+ } ;
146
123
}
147
124
public $vm : VueInstance ;
148
125
public $emit : VueInstance [ '$emit' ] ;
0 commit comments