From bc63df01992fdbf0b6749ad234153725697ed896 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 4 Sep 2024 20:53:12 +0800 Subject: [PATCH] fix(useTemplateRef): fix readonly warning when useTemplateRef has same variable name as template ref close #11795 close #11802 close #11804 --- .../__tests__/helpers/useTemplateRef.spec.ts | 21 +++++++++++++++++++ .../runtime-core/src/rendererTemplateRef.ts | 15 +++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/__tests__/helpers/useTemplateRef.spec.ts b/packages/runtime-core/__tests__/helpers/useTemplateRef.spec.ts index 9e4137da80f..10de6f48353 100644 --- a/packages/runtime-core/__tests__/helpers/useTemplateRef.spec.ts +++ b/packages/runtime-core/__tests__/helpers/useTemplateRef.spec.ts @@ -82,4 +82,25 @@ describe('useTemplateRef', () => { expect(`useTemplateRef('foo') already exists.`).toHaveBeenWarned() }) + + // #11795 + test('should work when variable name is same as key', () => { + let tRef + const key = 'refKey' + const Comp = { + setup() { + tRef = useTemplateRef(key) + return { + [key]: tRef, + } + }, + render() { + return h('div', { ref: key }) + }, + } + const root = nodeOps.createElement('div') + render(h(Comp), root) + + expect('target is readonly').not.toHaveBeenWarned() + }) }) diff --git a/packages/runtime-core/src/rendererTemplateRef.ts b/packages/runtime-core/src/rendererTemplateRef.ts index 647ce1fb42f..c7b15fe4022 100644 --- a/packages/runtime-core/src/rendererTemplateRef.ts +++ b/packages/runtime-core/src/rendererTemplateRef.ts @@ -63,12 +63,18 @@ export function setRef( const oldRef = oldRawRef && (oldRawRef as VNodeNormalizedRefAtom).r const refs = owner.refs === EMPTY_OBJ ? (owner.refs = {}) : owner.refs const setupState = owner.setupState + const canSetSetupRef = + setupState === EMPTY_OBJ + ? () => false + : (key: string) => + hasOwn(setupState, key) && + !(Object.getOwnPropertyDescriptor(refs, key) || EMPTY_OBJ).get // dynamic ref changed. unset old ref if (oldRef != null && oldRef !== ref) { if (isString(oldRef)) { refs[oldRef] = null - if (hasOwn(setupState, oldRef)) { + if (canSetSetupRef(oldRef)) { setupState[oldRef] = null } } else if (isRef(oldRef)) { @@ -81,11 +87,12 @@ export function setRef( } else { const _isString = isString(ref) const _isRef = isRef(ref) + if (_isString || _isRef) { const doSet = () => { if (rawRef.f) { const existing = _isString - ? hasOwn(setupState, ref) + ? canSetSetupRef(ref) ? setupState[ref] : refs[ref] : ref.value @@ -95,7 +102,7 @@ export function setRef( if (!isArray(existing)) { if (_isString) { refs[ref] = [refValue] - if (hasOwn(setupState, ref)) { + if (canSetSetupRef(ref)) { setupState[ref] = refs[ref] } } else { @@ -108,7 +115,7 @@ export function setRef( } } else if (_isString) { refs[ref] = value - if (hasOwn(setupState, ref)) { + if (canSetSetupRef(ref)) { setupState[ref] = value } } else if (_isRef) {