// state
props: Data
setupState: Data
+ refs: Data
+ metadata: WeakMap<Node, ElementMetadata>
/** directives */
dirs: Map<Node, DirectiveBinding[]>
- metadata: WeakMap<Node, ElementMetadata>
// lifecycle
isMounted: boolean
// state
props: EMPTY_OBJ,
setupState: EMPTY_OBJ,
+ refs: EMPTY_OBJ,
+ metadata: new WeakMap(),
dirs: new Map(),
- metadata: new WeakMap(),
// lifecycle
isMounted: false,
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'
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)
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})`)
}
--- /dev/null
+<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>