fix(compiler-vapor): properly handle static ref in inline mode

This commit is contained in:
daiwei 2025-04-29 15:26:53 +08:00
parent ea34f2f555
commit 3e69504c7d
3 changed files with 48 additions and 1 deletions

View File

@ -43,6 +43,24 @@ export function render(_ctx) {
}"
`;
exports[`compiler: template ref transform > static ref (PROD) 1`] = `
"
const _setTemplateRef = _createTemplateRefSetter()
const n0 = t0()
_setTemplateRef(n0, foo)
return n0
"
`;
exports[`compiler: template ref transform > static ref (inline mode) 1`] = `
"
const _setTemplateRef = _createTemplateRefSetter()
const n0 = t0()
_setTemplateRef(n0, foo)
return n0
"
`;
exports[`compiler: template ref transform > static ref 1`] = `
"import { createTemplateRefSetter as _createTemplateRefSetter, template as _template } from 'vue';
const t0 = _template("<div></div>", true)

View File

@ -1,3 +1,4 @@
import { BindingTypes } from '@vue/compiler-dom'
import {
DynamicFlag,
type ForIRNode,
@ -48,6 +49,16 @@ describe('compiler: template ref transform', () => {
expect(code).contains('_setTemplateRef(n0, "foo")')
})
test('static ref (inline mode)', () => {
const { code } = compileWithTransformRef(`<div ref="foo" />`, {
inline: true,
bindingMetadata: { foo: BindingTypes.SETUP_REF },
})
expect(code).matchSnapshot()
// pass the actual ref
expect(code).contains('_setTemplateRef(n0, foo)')
})
test('dynamic ref', () => {
const { ir, code } = compileWithTransformRef(`<div :ref="foo" />`)

View File

@ -2,6 +2,7 @@ import { genExpression } from './expression'
import type { CodegenContext } from '../generate'
import type { DeclareOldRefIRNode, SetTemplateRefIRNode } from '../ir'
import { type CodeFragment, NEWLINE, genCall } from './utils'
import { BindingTypes, type SimpleExpressionNode } from '@vue/compiler-dom'
export const setTemplateRefIdent = `_setTemplateRef`
@ -15,7 +16,7 @@ export function genSetTemplateRef(
...genCall(
setTemplateRefIdent, // will be generated in root scope
`n${oper.element}`,
genExpression(oper.value, context),
genRefValue(oper.value, context),
oper.effect ? `r${oper.element}` : oper.refFor ? 'void 0' : undefined,
oper.refFor && 'true',
),
@ -25,3 +26,20 @@ export function genSetTemplateRef(
export function genDeclareOldRef(oper: DeclareOldRefIRNode): CodeFragment[] {
return [NEWLINE, `let r${oper.id}`]
}
function genRefValue(value: SimpleExpressionNode, context: CodegenContext) {
// in inline mode there is no setupState object, so we can't use string
// keys to set the ref. Instead, we need to transform it to pass the
// actual ref instead.
if (!__BROWSER__ && value && context.options.inline) {
const binding = context.options.bindingMetadata[value.content]
if (
binding === BindingTypes.SETUP_LET ||
binding === BindingTypes.SETUP_REF ||
binding === BindingTypes.SETUP_MAYBE_REF
) {
return [value.content]
}
}
return genExpression(value, context)
}