Skip to content

Commit 03883bc

Browse files
edison11059romise
authored andcommitted
fix(templateRef): prevent unnecessary set ref on dynamic ref change or component unmount (#12642)
close #12639
1 parent cb629e4 commit 03883bc

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

packages/runtime-core/__tests__/rendererTemplateRef.spec.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
render,
1111
serializeInner,
1212
shallowRef,
13+
watch,
1314
} from '@vue/runtime-test'
1415

1516
describe('api: template refs', () => {
@@ -179,6 +180,89 @@ describe('api: template refs', () => {
179180
expect(el.value).toBe(null)
180181
})
181182

183+
// #12639
184+
it('update and unmount child in the same tick', async () => {
185+
const root = nodeOps.createElement('div')
186+
const el = ref(null)
187+
const toggle = ref(true)
188+
const show = ref(true)
189+
190+
const Comp = defineComponent({
191+
emits: ['change'],
192+
props: ['show'],
193+
setup(props, { emit }) {
194+
watch(
195+
() => props.show,
196+
() => {
197+
emit('change')
198+
},
199+
)
200+
return () => h('div', 'hi')
201+
},
202+
})
203+
204+
const App = {
205+
setup() {
206+
return {
207+
refKey: el,
208+
}
209+
},
210+
render() {
211+
return toggle.value
212+
? h(Comp, {
213+
ref: 'refKey',
214+
show: show.value,
215+
onChange: () => (toggle.value = false),
216+
})
217+
: null
218+
},
219+
}
220+
render(h(App), root)
221+
expect(el.value).not.toBe(null)
222+
223+
show.value = false
224+
await nextTick()
225+
expect(el.value).toBe(null)
226+
})
227+
228+
it('set and change ref in the same tick', async () => {
229+
const root = nodeOps.createElement('div')
230+
const show = ref(false)
231+
const refName = ref('a')
232+
233+
const Child = defineComponent({
234+
setup() {
235+
refName.value = 'b'
236+
return () => {}
237+
},
238+
})
239+
240+
const Comp = {
241+
render() {
242+
return h(Child, {
243+
ref: refName.value,
244+
})
245+
},
246+
updated(this: any) {
247+
expect(this.$refs.a).toBe(null)
248+
expect(this.$refs.b).not.toBe(null)
249+
},
250+
}
251+
252+
const App = {
253+
render() {
254+
return show.value ? h(Comp) : null
255+
},
256+
}
257+
258+
render(h(App), root)
259+
expect(refName.value).toBe('a')
260+
261+
show.value = true
262+
await nextTick()
263+
expect(refName.value).toBe('b')
264+
})
265+
182266
it('unset old ref when new ref is absent', async () => {
183267
const root1 = nodeOps.createElement('div')
184268
const root2 = nodeOps.createElement('div')

0 commit comments

Comments
 (0)