From: edison Date: Sat, 7 Jun 2025 00:39:31 +0000 (+0800) Subject: Merge branch 'main' into edison/fix/12639 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d10ebd6e93fa9bbb72177cdc9fbdccb4cc4c538c;p=thirdparty%2Fvuejs%2Fcore.git Merge branch 'main' into edison/fix/12639 --- d10ebd6e93fa9bbb72177cdc9fbdccb4cc4c538c diff --cc packages/runtime-core/__tests__/rendererTemplateRef.spec.ts index b9e5740d08,7803826e3d..cc0a5b5bbf --- a/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts +++ b/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts @@@ -180,87 -179,35 +180,118 @@@ describe('api: template refs', () => expect(el.value).toBe(null) }) + // #12639 + it('update and unmount child in the same tick', async () => { + const root = nodeOps.createElement('div') + const el = ref(null) + const toggle = ref(true) + const show = ref(true) + + const Comp = defineComponent({ + emits: ['change'], + props: ['show'], + setup(props, { emit }) { + watch( + () => props.show, + () => { + emit('change') + }, + ) + return () => h('div', 'hi') + }, + }) + + const App = { + setup() { + return { + refKey: el, + } + }, + render() { + return toggle.value + ? h(Comp, { + ref: 'refKey', + show: show.value, + onChange: () => (toggle.value = false), + }) + : null + }, + } + render(h(App), root) + expect(el.value).not.toBe(null) + + show.value = false + await nextTick() + expect(el.value).toBe(null) + }) + + it('set and change ref in the same tick', async () => { + const root = nodeOps.createElement('div') + const show = ref(false) + const refName = ref('a') + + const Child = defineComponent({ + setup() { + refName.value = 'b' + return () => {} + }, + }) + + const Comp = { + render() { + return h(Child, { + ref: refName.value, + }) + }, + updated(this: any) { + expect(this.$refs.a).toBe(null) + expect(this.$refs.b).not.toBe(null) + }, + } + + const App = { + render() { + return show.value ? h(Comp) : null + }, + } + + render(h(App), root) + expect(refName.value).toBe('a') + + show.value = true + await nextTick() - expect(refName.value).toBe('b') ++ expect(refName.value).toBe('b') ++ }) ++ + it('unset old ref when new ref is absent', async () => { + const root1 = nodeOps.createElement('div') + const root2 = nodeOps.createElement('div') + const el1 = ref(null) + const el2 = ref(null) + const toggle = ref(true) + + const Comp1 = { + setup() { + return () => (toggle.value ? h('div', { ref: el1 }) : h('div')) + }, + } + + const Comp2 = { + setup() { + return () => h('div', { ref: toggle.value ? el2 : undefined }) + }, + } + + render(h(Comp1), root1) + render(h(Comp2), root2) + + expect(el1.value).toBe(root1.children[0]) + expect(el2.value).toBe(root2.children[0]) + + toggle.value = false + await nextTick() + expect(el1.value).toBe(null) + expect(el2.value).toBe(null) }) test('string ref inside slots', async () => {