]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor: move template ref setter into dedicated file
authorEvan You <yyx990803@gmail.com>
Sat, 11 Dec 2021 01:05:51 +0000 (09:05 +0800)
committerEvan You <yyx990803@gmail.com>
Sat, 11 Dec 2021 02:09:21 +0000 (10:09 +0800)
packages/runtime-core/__tests__/rendererTemplateRef.spec.ts [moved from packages/runtime-core/__tests__/apiTemplateRef.spec.ts with 100% similarity]
packages/runtime-core/src/components/KeepAlive.ts
packages/runtime-core/src/hydration.ts
packages/runtime-core/src/renderer.ts
packages/runtime-core/src/rendererTemplateRef.ts [new file with mode: 0644]
packages/runtime-core/src/vnode.ts

index 223a7c602f55d555b75d8065e7719e15b3b820f9..c6180019f86cdc7507761f3da48fdcf3b8abe000 100644 (file)
@@ -8,7 +8,13 @@ import {
   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,
@@ -30,8 +36,7 @@ import {
   queuePostRenderEffect,
   MoveType,
   RendererElement,
-  RendererNode,
-  invokeVNodeHook
+  RendererNode
 } from '../renderer'
 import { setTransitionHooks } from './BaseTransition'
 import { ComponentRenderContext } from '../componentPublicInstance'
index 517b1495c1111f0e387526c06ef0c4516ecbc370..f405aac45fa5a988732d5bb3588ceb7a0ff91f51 100644 (file)
@@ -7,14 +7,16 @@ import {
   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,
index 073ff91be10a0d982d43149d36d4502a336cfb46..04bebdb1f0e76b216cc471791c945a04aa1385f6 100644 (file)
@@ -9,17 +9,15 @@ import {
   createVNode,
   isSameVNodeType,
   Static,
-  VNodeNormalizedRef,
   VNodeHook,
-  VNodeNormalizedRefAtom,
-  VNodeProps
+  VNodeProps,
+  invokeVNodeHook
 } from './vnode'
 import {
   ComponentInternalInstance,
   ComponentOptions,
   createComponentInstance,
   Data,
-  getExposeProxy,
   setupComponent
 } from './component'
 import {
@@ -29,19 +27,15 @@ 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,
@@ -51,16 +45,12 @@ import {
   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,
@@ -69,11 +59,6 @@ import {
 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'
@@ -2351,124 +2336,6 @@ function baseCreateRenderer(
   }
 }
 
-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
diff --git a/packages/runtime-core/src/rendererTemplateRef.ts b/packages/runtime-core/src/rendererTemplateRef.ts
new file mode 100644 (file)
index 0000000..249fb9e
--- /dev/null
@@ -0,0 +1,127 @@
+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})`)
+    }
+  }
+}
index a70d93e39770b55e2e2cc943b4381a2406acae23..0db4005c8779f584e2e33adb9d17e0af095dd9b9 100644 (file)
@@ -42,6 +42,7 @@ import { hmrDirtyComponents } from './hmr'
 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
@@ -811,3 +812,15 @@ export function mergeProps(...args: (Data & VNodeProps)[]) {
   }
   return ret
 }
+
+export function invokeVNodeHook(
+  hook: VNodeHook,
+  instance: ComponentInternalInstance | null,
+  vnode: VNode,
+  prevVNode: VNode | null = null
+) {
+  callWithAsyncErrorHandling(hook, instance, ErrorCodes.VNODE_HOOK, [
+    vnode,
+    prevVNode
+  ])
+}