getComponentName,
ComponentOptions
} from '../component'
-import { VNode, cloneVNode, isVNode, VNodeProps } from '../vnode'
+import {
+ VNode,
+ cloneVNode,
+ isVNode,
+ VNodeProps,
+ invokeVNodeHook
+} from '../vnode'
import { warn } from '../warning'
import {
onBeforeUnmount,
queuePostRenderEffect,
MoveType,
RendererElement,
- RendererNode,
- invokeVNodeHook
+ RendererNode
} from '../renderer'
import { setTransitionHooks } from './BaseTransition'
import { ComponentRenderContext } from '../componentPublicInstance'
Fragment,
VNodeHook,
createVNode,
- createTextVNode
+ createTextVNode,
+ invokeVNodeHook
} from './vnode'
import { flushPostFlushCbs } from './scheduler'
import { ComponentInternalInstance } from './component'
import { invokeDirectiveHook } from './directives'
import { warn } from './warning'
import { PatchFlags, ShapeFlags, isReservedProp, isOn } from '@vue/shared'
-import { RendererInternals, invokeVNodeHook, setRef } from './renderer'
+import { RendererInternals } from './renderer'
+import { setRef } from './rendererTemplateRef'
import {
SuspenseImpl,
SuspenseBoundary,
createVNode,
isSameVNodeType,
Static,
- VNodeNormalizedRef,
VNodeHook,
- VNodeNormalizedRefAtom,
- VNodeProps
+ VNodeProps,
+ invokeVNodeHook
} from './vnode'
import {
ComponentInternalInstance,
ComponentOptions,
createComponentInstance,
Data,
- getExposeProxy,
setupComponent
} from './component'
import {
updateHOCHostEl
} from './componentRenderUtils'
import {
- isString,
EMPTY_OBJ,
EMPTY_ARR,
isReservedProp,
- isFunction,
PatchFlags,
ShapeFlags,
NOOP,
- hasOwn,
invokeArrayFns,
isArray,
- getGlobalThis,
- remove
+ getGlobalThis
} from '@vue/shared'
import {
queueJob,
flushPreFlushCbs,
SchedulerJob
} from './scheduler'
-import {
- isRef,
- pauseTracking,
- resetTracking,
- ReactiveEffect
-} from '@vue/reactivity'
+import { pauseTracking, resetTracking, ReactiveEffect } from '@vue/reactivity'
import { updateProps } from './componentProps'
import { updateSlots } from './componentSlots'
import { pushWarningContext, popWarningContext, warn } from './warning'
import { createAppAPI, CreateAppFunction } from './apiCreateApp'
+import { setRef } from './rendererTemplateRef'
import {
SuspenseBoundary,
queueEffectWithSuspense,
import { TeleportImpl, TeleportVNode } from './components/Teleport'
import { isKeepAlive, KeepAliveContext } from './components/KeepAlive'
import { registerHMR, unregisterHMR, isHmrUpdating } from './hmr'
-import {
- ErrorCodes,
- callWithErrorHandling,
- callWithAsyncErrorHandling
-} from './errorHandling'
import { createHydrationFunctions, RootHydrateFunction } from './hydration'
import { invokeDirectiveHook } from './directives'
import { startMeasure, endMeasure } from './profiling'
}
}
-export function setRef(
- rawRef: VNodeNormalizedRef,
- oldRawRef: VNodeNormalizedRef | null,
- parentSuspense: SuspenseBoundary | null,
- vnode: VNode,
- isUnmount = false
-) {
- if (isArray(rawRef)) {
- rawRef.forEach((r, i) =>
- setRef(
- r,
- oldRawRef && (isArray(oldRawRef) ? oldRawRef[i] : oldRawRef),
- parentSuspense,
- vnode,
- isUnmount
- )
- )
- return
- }
-
- if (isAsyncWrapper(vnode) && !isUnmount) {
- // when mounting async components, nothing needs to be done,
- // because the template ref is forwarded to inner component
- return
- }
-
- const refValue =
- vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT
- ? getExposeProxy(vnode.component!) || vnode.component!.proxy
- : vnode.el
- const value = isUnmount ? null : refValue
-
- const { i: owner, r: ref } = rawRef
- if (__DEV__ && !owner) {
- warn(
- `Missing ref owner context. ref cannot be used on hoisted vnodes. ` +
- `A vnode with ref must be created inside the render function.`
- )
- return
- }
- const oldRef = oldRawRef && (oldRawRef as VNodeNormalizedRefAtom).r
- const refs = owner.refs === EMPTY_OBJ ? (owner.refs = {}) : owner.refs
- const setupState = owner.setupState
-
- // dynamic ref changed. unset old ref
- if (oldRef != null && oldRef !== ref) {
- if (isString(oldRef)) {
- refs[oldRef] = null
- if (hasOwn(setupState, oldRef)) {
- setupState[oldRef] = null
- }
- } else if (isRef(oldRef)) {
- oldRef.value = null
- }
- }
-
- if (isFunction(ref)) {
- callWithErrorHandling(ref, owner, ErrorCodes.FUNCTION_REF, [value, refs])
- } else {
- const _isString = isString(ref)
- const _isRef = isRef(ref)
- if (_isString || _isRef) {
- const doSet = () => {
- if (rawRef.f) {
- const existing = _isString ? refs[ref] : ref.value
- if (isUnmount) {
- isArray(existing) && remove(existing, refValue)
- } else {
- if (!isArray(existing)) {
- if (_isString) {
- refs[ref] = [refValue]
- } else {
- ref.value = [refValue]
- if (rawRef.k) refs[rawRef.k] = ref.value
- }
- } else if (!existing.includes(refValue)) {
- existing.push(refValue)
- }
- }
- } else if (_isString) {
- refs[ref] = value
- if (hasOwn(setupState, ref)) {
- setupState[ref] = value
- }
- } else if (isRef(ref)) {
- ref.value = value
- if (rawRef.k) refs[rawRef.k] = value
- } else if (__DEV__) {
- warn('Invalid template ref type:', ref, `(${typeof ref})`)
- }
- }
- if (value) {
- // #1789: for non-null values, set them after render
- // null values means this is unmount and it should not overwrite another
- // ref with the same key
- ;(doSet as SchedulerJob).id = -1
- queuePostRenderEffect(doSet, parentSuspense)
- } else {
- doSet()
- }
- } else if (__DEV__) {
- warn('Invalid template ref type:', ref, `(${typeof ref})`)
- }
- }
-}
-
-export function invokeVNodeHook(
- hook: VNodeHook,
- instance: ComponentInternalInstance | null,
- vnode: VNode,
- prevVNode: VNode | null = null
-) {
- callWithAsyncErrorHandling(hook, instance, ErrorCodes.VNODE_HOOK, [
- vnode,
- prevVNode
- ])
-}
-
function toggleRecurse(
{ effect, update }: ComponentInternalInstance,
allowed: boolean
--- /dev/null
+import { SuspenseBoundary } from './components/Suspense'
+import { VNode, VNodeNormalizedRef, VNodeNormalizedRefAtom } from './vnode'
+import {
+ EMPTY_OBJ,
+ hasOwn,
+ isArray,
+ isFunction,
+ isString,
+ remove,
+ ShapeFlags
+} from '@vue/shared'
+import { isAsyncWrapper } from './apiAsyncComponent'
+import { getExposeProxy } from './component'
+import { warn } from './warning'
+import { isRef } from '@vue/reactivity'
+import { callWithErrorHandling, ErrorCodes } from './errorHandling'
+import { SchedulerJob } from './scheduler'
+import { queuePostRenderEffect } from './renderer'
+
+/**
+ * Function for handling a template ref
+ */
+export function setRef(
+ rawRef: VNodeNormalizedRef,
+ oldRawRef: VNodeNormalizedRef | null,
+ parentSuspense: SuspenseBoundary | null,
+ vnode: VNode,
+ isUnmount = false
+) {
+ if (isArray(rawRef)) {
+ rawRef.forEach((r, i) =>
+ setRef(
+ r,
+ oldRawRef && (isArray(oldRawRef) ? oldRawRef[i] : oldRawRef),
+ parentSuspense,
+ vnode,
+ isUnmount
+ )
+ )
+ return
+ }
+
+ if (isAsyncWrapper(vnode) && !isUnmount) {
+ // when mounting async components, nothing needs to be done,
+ // because the template ref is forwarded to inner component
+ return
+ }
+
+ const refValue =
+ vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT
+ ? getExposeProxy(vnode.component!) || vnode.component!.proxy
+ : vnode.el
+ const value = isUnmount ? null : refValue
+
+ const { i: owner, r: ref } = rawRef
+ if (__DEV__ && !owner) {
+ warn(
+ `Missing ref owner context. ref cannot be used on hoisted vnodes. ` +
+ `A vnode with ref must be created inside the render function.`
+ )
+ return
+ }
+ const oldRef = oldRawRef && (oldRawRef as VNodeNormalizedRefAtom).r
+ const refs = owner.refs === EMPTY_OBJ ? (owner.refs = {}) : owner.refs
+ const setupState = owner.setupState
+
+ // dynamic ref changed. unset old ref
+ if (oldRef != null && oldRef !== ref) {
+ if (isString(oldRef)) {
+ refs[oldRef] = null
+ if (hasOwn(setupState, oldRef)) {
+ setupState[oldRef] = null
+ }
+ } else if (isRef(oldRef)) {
+ oldRef.value = null
+ }
+ }
+
+ if (isFunction(ref)) {
+ callWithErrorHandling(ref, owner, ErrorCodes.FUNCTION_REF, [value, refs])
+ } else {
+ const _isString = isString(ref)
+ const _isRef = isRef(ref)
+ if (_isString || _isRef) {
+ const doSet = () => {
+ if (rawRef.f) {
+ const existing = _isString ? refs[ref] : ref.value
+ if (isUnmount) {
+ isArray(existing) && remove(existing, refValue)
+ } else {
+ if (!isArray(existing)) {
+ if (_isString) {
+ refs[ref] = [refValue]
+ } else {
+ ref.value = [refValue]
+ if (rawRef.k) refs[rawRef.k] = ref.value
+ }
+ } else if (!existing.includes(refValue)) {
+ existing.push(refValue)
+ }
+ }
+ } else if (_isString) {
+ refs[ref] = value
+ if (hasOwn(setupState, ref)) {
+ setupState[ref] = value
+ }
+ } else if (isRef(ref)) {
+ ref.value = value
+ if (rawRef.k) refs[rawRef.k] = value
+ } else if (__DEV__) {
+ warn('Invalid template ref type:', ref, `(${typeof ref})`)
+ }
+ }
+ if (value) {
+ // #1789: for non-null values, set them after render
+ // null values means this is unmount and it should not overwrite another
+ // ref with the same key
+ ;(doSet as SchedulerJob).id = -1
+ queuePostRenderEffect(doSet, parentSuspense)
+ } else {
+ doSet()
+ }
+ } else if (__DEV__) {
+ warn('Invalid template ref type:', ref, `(${typeof ref})`)
+ }
+ }
+}
import { convertLegacyComponent } from './compat/component'
import { convertLegacyVModelProps } from './compat/componentVModel'
import { defineLegacyVNodeProperties } from './compat/renderFn'
+import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
export const Fragment = Symbol(__DEV__ ? 'Fragment' : undefined) as any as {
__isFragment: true
}
return ret
}
+
+export function invokeVNodeHook(
+ hook: VNodeHook,
+ instance: ComponentInternalInstance | null,
+ vnode: VNode,
+ prevVNode: VNode | null = null
+) {
+ callWithAsyncErrorHandling(hook, instance, ErrorCodes.VNODE_HOOK, [
+ vnode,
+ prevVNode
+ ])
+}