File tree 3 files changed +48
-7
lines changed
3 files changed +48
-7
lines changed Original file line number Diff line number Diff line change @@ -14,7 +14,7 @@ import {
14
14
import { ref } from './apis'
15
15
import vmStateManager from './utils/vmStateManager'
16
16
import {
17
- updateTemplateRef ,
17
+ afterRender ,
18
18
activateCurrentInstance ,
19
19
resolveScopedSlots ,
20
20
asVmProperty ,
@@ -31,16 +31,13 @@ export function mixin(Vue: VueConstructor) {
31
31
Vue . mixin ( {
32
32
beforeCreate : functionApiInit ,
33
33
mounted ( this : ComponentInstance ) {
34
- updateTemplateRef ( this )
34
+ afterRender ( this )
35
35
} ,
36
36
beforeUpdate ( ) {
37
37
updateVmAttrs ( this as ComponentInstance )
38
38
} ,
39
39
updated ( this : ComponentInstance ) {
40
- updateTemplateRef ( this )
41
- if ( this . $vnode ?. context ) {
42
- updateTemplateRef ( this . $vnode . context )
43
- }
40
+ afterRender ( this )
44
41
} ,
45
42
} )
46
43
Original file line number Diff line number Diff line change
1
+ import type { VNode } from 'vue'
1
2
import { ComponentInstance } from '../component'
2
3
import vmStateManager from './vmStateManager'
3
4
import {
@@ -76,7 +77,7 @@ export function asVmProperty(
76
77
}
77
78
}
78
79
79
- export function updateTemplateRef ( vm : ComponentInstance ) {
80
+ function updateTemplateRef ( vm : ComponentInstance ) {
80
81
const rawBindings = vmStateManager . get ( vm , 'rawBindings' ) || { }
81
82
if ( ! rawBindings || ! Object . keys ( rawBindings ) . length ) return
82
83
@@ -103,6 +104,19 @@ export function updateTemplateRef(vm: ComponentInstance) {
103
104
vmStateManager . set ( vm , 'refs' , validNewKeys )
104
105
}
105
106
107
+ export function afterRender ( vm : ComponentInstance ) {
108
+ const stack = [ ( vm as any ) . _vnode as VNode ]
109
+ while ( stack . length ) {
110
+ const vnode = stack . pop ( ) !
111
+ if ( vnode . context ) updateTemplateRef ( vnode . context )
112
+ if ( vnode . children ) {
113
+ for ( let i = 0 ; i < vnode . children . length ; ++ i ) {
114
+ stack . push ( vnode . children [ i ] )
115
+ }
116
+ }
117
+ }
118
+ }
119
+
106
120
export function updateVmAttrs ( vm : ComponentInstance , ctx ?: SetupContext ) {
107
121
if ( ! vm ) {
108
122
return
Original file line number Diff line number Diff line change @@ -113,6 +113,36 @@ describe('ref', () => {
113
113
//@ts -ignore
114
114
expect ( vm . $refs . barRef ) . toBe ( vm . barRef )
115
115
} )
116
+
117
+ it ( 'should update deeply nested component refs using scoped slots' , async ( ) => {
118
+ const vm = new Vue ( {
119
+ setup ( ) {
120
+ const divRef = ref ( null )
121
+ const showDiv = ref ( false )
122
+ return {
123
+ divRef,
124
+ showDiv,
125
+ }
126
+ } ,
127
+ template : `<div><foo #default>Slot: <div ref="divRef" v-if="showDiv" /></foo></div>` ,
128
+ components : {
129
+ foo : {
130
+ components : {
131
+ bar : {
132
+ template : `<div><slot /></div>` ,
133
+ } ,
134
+ } ,
135
+ template : '<div><bar #default><slot /></bar></div>' ,
136
+ } ,
137
+ } ,
138
+ } ) . $mount ( )
139
+ await nextTick ( )
140
+ //@ts -ignore
141
+ vm . showDiv = true
142
+ await nextTick ( )
143
+ //@ts -ignore
144
+ expect ( vm . $refs . divRef ) . toBe ( vm . divRef )
145
+ } )
116
146
// TODO: how ?
117
147
// it('work with createElement', () => {
118
148
// let root;
You can’t perform that action at this time.
0 commit comments