]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(runtime-vapor): template refs
author三咲智子 Kevin Deng <sxzz@sxzz.moe>
Sun, 21 Jan 2024 05:59:56 +0000 (13:59 +0800)
committer三咲智子 Kevin Deng <sxzz@sxzz.moe>
Sun, 21 Jan 2024 05:59:56 +0000 (13:59 +0800)
packages/runtime-vapor/src/component.ts
packages/runtime-vapor/src/dom/templateRef.ts
playground/src/refs.vue [new file with mode: 0644]

index 9b811086194c65ef444641420073f50ea0be8fad..d79ae582f197cc8b51833e3a5c2168f8e0be9e65 100644 (file)
@@ -44,10 +44,11 @@ export interface ComponentInternalInstance {
   // state
   props: Data
   setupState: Data
+  refs: Data
+  metadata: WeakMap<Node, ElementMetadata>
 
   /** directives */
   dirs: Map<Node, DirectiveBinding[]>
-  metadata: WeakMap<Node, ElementMetadata>
 
   // lifecycle
   isMounted: boolean
@@ -154,9 +155,10 @@ export const createComponentInstance = (
     // state
     props: EMPTY_OBJ,
     setupState: EMPTY_OBJ,
+    refs: EMPTY_OBJ,
+    metadata: new WeakMap(),
 
     dirs: new Map(),
-    metadata: new WeakMap(),
 
     // lifecycle
     isMounted: false,
index fcedbd1e20a8f090aad7c605edb09bb442796097..df895c0f61d5d15361b0455bb5e3478ca497836a 100644 (file)
@@ -1,7 +1,7 @@
 import { type Ref, type SchedulerJob, isRef } from '@vue/reactivity'
 import { currentInstance } from '../component'
 import { VaporErrorCodes, callWithErrorHandling } from '../errorHandling'
-import { hasOwn, isFunction, isString } from '@vue/shared'
+import { EMPTY_OBJ, hasOwn, isFunction, isString } from '@vue/shared'
 import { warn } from '../warning'
 import { queuePostRenderEffect } from '../scheduler'
 
@@ -14,10 +14,16 @@ export function setRef(el: Element, ref: NodeRef) {
   if (!currentInstance) return
   const { setupState, isUnmounted } = currentInstance
 
+  const value = isUnmounted ? null : el
+  const refs =
+    currentInstance.refs === EMPTY_OBJ
+      ? (currentInstance.refs = {})
+      : currentInstance.refs
+
   if (isFunction(ref)) {
     callWithErrorHandling(ref, currentInstance, VaporErrorCodes.FUNCTION_REF, [
-      el,
-      // refs,
+      value,
+      refs,
     ])
   } else {
     const _isString = isString(ref)
@@ -26,11 +32,12 @@ export function setRef(el: Element, ref: NodeRef) {
     if (_isString || _isRef) {
       const doSet = () => {
         if (_isString) {
+          refs[ref] = value
           if (hasOwn(setupState, ref)) {
-            setupState[ref] = el
+            setupState[ref] = value
           }
         } else if (_isRef) {
-          ref.value = el
+          ref.value = value
         } else if (__DEV__) {
           warn('Invalid template ref type:', ref, `(${typeof ref})`)
         }
diff --git a/playground/src/refs.vue b/playground/src/refs.vue
new file mode 100644 (file)
index 0000000..17dbc7e
--- /dev/null
@@ -0,0 +1,23 @@
+<script setup lang="ts">
+import { Data } from '@vue/shared'
+import { ref, onMounted } from 'vue/vapor'
+
+const inputRef = ref()
+const buttonRef = ref()
+
+function handleSetRef(el: HTMLButtonElement, refs: Data) {
+  buttonRef.value = el
+  console.log(el, refs)
+}
+
+onMounted(() => {
+  console.log(inputRef.value, buttonRef.value)
+})
+</script>
+
+<template>
+  <div>
+    <input type="text" ref="inputRef" />
+    <button :ref="handleSetRef">Button</button>
+  </div>
+</template>