diff --git a/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts b/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts index 53e03c827b9..2663601d296 100644 --- a/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts +++ b/packages/runtime-core/__tests__/rendererTemplateRef.spec.ts @@ -111,6 +111,26 @@ describe('api: template refs', () => { expect(fn2.mock.calls[0][0]).toBe(root.children[0]) }) + it('function ref should not track dependencies read by callback', async () => { + const root = nodeOps.createElement('div') + const visible = ref(new Set()) + const fn = vi.fn((el: any) => { + if (!el || visible.value.has(0)) { + return + } + visible.value = new Set([0]) + }) + + const Comp = defineComponent(() => () => h('div', { ref: fn })) + + render(h(Comp), root) + expect(fn).toHaveBeenCalledTimes(1) + expect(visible.value.has(0)).toBe(true) + + await nextTick() + expect(fn).toHaveBeenCalledTimes(1) + }) + it('function ref unmount', async () => { const root = nodeOps.createElement('div') const fn = vi.fn() diff --git a/packages/runtime-core/src/rendererTemplateRef.ts b/packages/runtime-core/src/rendererTemplateRef.ts index 737c1c8c38a..42925c39633 100644 --- a/packages/runtime-core/src/rendererTemplateRef.ts +++ b/packages/runtime-core/src/rendererTemplateRef.ts @@ -17,7 +17,7 @@ import { } from '@vue/shared' import { isAsyncWrapper } from './apiAsyncComponent' import { warn } from './warning' -import { isRef, toRaw } from '@vue/reactivity' +import { isRef, pauseTracking, resetTracking, toRaw } from '@vue/reactivity' import { ErrorCodes, callWithErrorHandling } from './errorHandling' import { type SchedulerJob, SchedulerJobFlags } from './scheduler' import { queuePostRenderEffect } from './renderer' @@ -136,7 +136,12 @@ export function setRef( } if (isFunction(ref)) { - callWithErrorHandling(ref, owner, ErrorCodes.FUNCTION_REF, [value, refs]) + pauseTracking() + try { + callWithErrorHandling(ref, owner, ErrorCodes.FUNCTION_REF, [value, refs]) + } finally { + resetTracking() + } } else { const _isString = isString(ref) const _isRef = isRef(ref)