Skip to content

Commit ccd1ddf

Browse files
authored
fix(templateRef): don't update setup ref for useTemplateRef key (#14444)
sync https://github.com/vuejs/core/pull/12756/changes
1 parent 102b32b commit ccd1ddf

3 files changed

Lines changed: 58 additions & 6 deletions

File tree

packages/runtime-core/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -687,4 +687,4 @@ export {
687687
/**
688688
* @internal
689689
*/
690-
export { knownTemplateRefs } from './helpers/useTemplateRef'
690+
export { knownTemplateRefs, isTemplateRefKey } from './helpers/useTemplateRef'

packages/runtime-vapor/__tests__/dom/templateRef.spec.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,51 @@ describe('api: template ref', () => {
938938
}
939939
})
940940

941+
// #12749
942+
test(`don't update setup ref for useTemplateRef key`, () => {
943+
let foo: ShallowRef
944+
let bar: ReturnType<typeof ref>
945+
const { host } = define({
946+
setup() {
947+
foo = useTemplateRef('bar')
948+
bar = ref(null)
949+
return { bar }
950+
},
951+
render() {
952+
const n0 = template('<div></div>')() as Element
953+
createTemplateRefSetter()(n0, 'bar')
954+
return n0
955+
},
956+
}).render()
957+
958+
expect(bar!.value).toBe(null)
959+
expect(foo!.value).toBe(host.children[0])
960+
})
961+
962+
test(`don't update setup ref for useTemplateRef key (compiled in prod mode)`, () => {
963+
__DEV__ = false
964+
try {
965+
let foo: ReturnType<typeof ref>
966+
let fooRef: ShallowRef
967+
const { host } = define({
968+
setup() {
969+
foo = ref('hello')
970+
fooRef = useTemplateRef('foo')
971+
},
972+
render() {
973+
const n0 = template('<div></div>')() as Element
974+
createTemplateRefSetter()(n0, foo!, false, 'foo')
975+
return n0
976+
},
977+
}).render()
978+
979+
expect(foo!.value).toBe('hello')
980+
expect(fooRef!.value).toBe(host.children[0])
981+
} finally {
982+
__DEV__ = true
983+
}
984+
})
985+
941986
// TODO: can not reproduce in Vapor
942987
// // #2078
943988
// test('handling multiple merged refs', async () => {

packages/runtime-vapor/src/apiTemplateRef.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
callWithErrorHandling,
1212
createCanSetSetupRefChecker,
1313
isAsyncWrapper,
14+
isTemplateRefKey,
1415
knownTemplateRefs,
1516
queuePostFlushCb,
1617
warn,
@@ -104,8 +105,14 @@ export function setRef(
104105
? createCanSetSetupRefChecker(setupState, refs)
105106
: NO
106107

107-
const canSetRef = (ref: NodeRef) => {
108-
return !__DEV__ || !knownTemplateRefs.has(ref as any)
108+
const canSetRef = (ref: NodeRef, key?: string) => {
109+
if (__DEV__ && knownTemplateRefs.has(ref as any)) {
110+
return false
111+
}
112+
if (key && isTemplateRefKey(refs, key)) {
113+
return false
114+
}
115+
return true
109116
}
110117

111118
// dynamic ref changed. unset old ref
@@ -158,7 +165,7 @@ export function setRef(
158165
existing = setupState[ref]
159166
}
160167
} else {
161-
if (canSetRef(ref)) ref.value = existing
168+
if (canSetRef(ref, refKey)) ref.value = existing
162169
if (refKey) refs[refKey] = existing
163170
}
164171
} else if (!existing.includes(refValue)) {
@@ -170,7 +177,7 @@ export function setRef(
170177
setupState[ref] = refValue
171178
}
172179
} else if (_isRef) {
173-
if (canSetRef(ref)) ref.value = refValue
180+
if (canSetRef(ref, refKey)) ref.value = refValue
174181
if (refKey) refs[refKey] = refValue
175182
} else if (__DEV__) {
176183
warn('Invalid template ref type:', ref, `(${typeof ref})`)
@@ -188,7 +195,7 @@ export function setRef(
188195
setupState[ref] = null
189196
}
190197
} else if (_isRef) {
191-
if (canSetRef(ref)) ref.value = null
198+
if (canSetRef(ref, refKey)) ref.value = null
192199
if (refKey) refs[refKey] = null
193200
}
194201
})

0 commit comments

Comments
 (0)