refactor(runtime-vapor): template refs

This commit is contained in:
三咲智子 Kevin Deng 2024-01-21 13:59:56 +08:00
parent 1d11ed72fb
commit 32604cf91c
No known key found for this signature in database
GPG Key ID: 69992F2250DFD93E
3 changed files with 39 additions and 7 deletions

View 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,

View 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})`)
}

23
playground/src/refs.vue Normal file
View File

@ -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>