Skip to content

Commit 4cd282b

Browse files
authored
fix(compiler): generate function ref for script setup if inline is ture. (#4492)
1 parent 8580796 commit 4cd282b

File tree

2 files changed

+98
-15
lines changed

2 files changed

+98
-15
lines changed

Diff for: packages/compiler-core/__tests__/transforms/transformElement.spec.ts

+68
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,74 @@ describe('compiler: element transform', () => {
936936
expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_PATCH))
937937
})
938938

939+
test('the binding exists (inline ref input)', () => {
940+
const { node } = parseWithElementTransform(`<input ref="input"/>`, {
941+
inline: true,
942+
bindingMetadata: {
943+
input: BindingTypes.SETUP_REF
944+
}
945+
})
946+
expect(node.props).toMatchObject({
947+
type: NodeTypes.JS_OBJECT_EXPRESSION,
948+
properties: [
949+
{
950+
type: NodeTypes.JS_PROPERTY,
951+
key: {
952+
type: NodeTypes.SIMPLE_EXPRESSION,
953+
content: 'ref',
954+
isStatic: true
955+
},
956+
value: {
957+
type: NodeTypes.JS_FUNCTION_EXPRESSION,
958+
params: ['_value', '_refs'],
959+
body: {
960+
type: NodeTypes.JS_BLOCK_STATEMENT,
961+
body: [
962+
{
963+
content: `_refs['input'] = _value`
964+
},
965+
{
966+
content: 'input.value = _value'
967+
}
968+
]
969+
}
970+
}
971+
}
972+
]
973+
})
974+
})
975+
976+
test('the binding not exists (inline ref input)', () => {
977+
const { node } = parseWithElementTransform(`<input ref="input"/>`, {
978+
inline: true
979+
})
980+
expect(node.props).toMatchObject({
981+
type: NodeTypes.JS_OBJECT_EXPRESSION,
982+
properties: [
983+
{
984+
type: NodeTypes.JS_PROPERTY,
985+
key: {
986+
type: NodeTypes.SIMPLE_EXPRESSION,
987+
content: 'ref',
988+
isStatic: true
989+
},
990+
value: {
991+
type: NodeTypes.JS_FUNCTION_EXPRESSION,
992+
params: ['_value', '_refs'],
993+
body: {
994+
type: NodeTypes.JS_BLOCK_STATEMENT,
995+
body: [
996+
{
997+
content: `_refs['input'] = _value`
998+
}
999+
]
1000+
}
1001+
}
1002+
}
1003+
]
1004+
})
1005+
})
1006+
9391007
test('HYDRATE_EVENTS', () => {
9401008
// ignore click events (has dedicated fast path)
9411009
const { node } = parseWithElementTransform(`<div @click="foo" />`, {

Diff for: packages/compiler-core/src/transforms/transformElement.ts

+30-15
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ import {
1919
TemplateTextChildNode,
2020
DirectiveArguments,
2121
createVNodeCall,
22-
ConstantTypes
22+
ConstantTypes,
23+
JSChildNode,
24+
createFunctionExpression,
25+
createBlockStatement
2326
} from '../ast'
2427
import {
2528
PatchFlags,
@@ -58,7 +61,7 @@ import {
5861
} from '../utils'
5962
import { buildSlots } from './vSlot'
6063
import { getConstantType } from './hoistStatic'
61-
import { BindingTypes } from '../options'
64+
import { BindingMetadata, BindingTypes } from '../options'
6265
import {
6366
checkCompatEnabled,
6467
CompilerDeprecationTypes,
@@ -459,19 +462,21 @@ export function buildProps(
459462
const prop = props[i]
460463
if (prop.type === NodeTypes.ATTRIBUTE) {
461464
const { loc, name, value } = prop
462-
let isStatic = true
465+
let valueNode = createSimpleExpression(
466+
value ? value.content : '',
467+
true,
468+
value ? value.loc : loc
469+
) as JSChildNode
463470
if (name === 'ref') {
464471
hasRef = true
465472
// in inline mode there is no setupState object, so we can't use string
466473
// keys to set the ref. Instead, we need to transform it to pass the
467474
// acrtual ref instead.
468-
if (
469-
!__BROWSER__ &&
470-
value &&
471-
context.inline &&
472-
context.bindingMetadata[value.content]
473-
) {
474-
isStatic = false
475+
if (!__BROWSER__ && context.inline && value?.content) {
476+
valueNode = createFunctionExpression(['_value', '_refs'])
477+
valueNode.body = createBlockStatement(
478+
processInlineRef(context.bindingMetadata, value.content)
479+
)
475480
}
476481
}
477482
// skip is on <component>, or is="vue:xxx"
@@ -494,11 +499,7 @@ export function buildProps(
494499
true,
495500
getInnerRange(loc, 0, name.length)
496501
),
497-
createSimpleExpression(
498-
value ? value.content : '',
499-
isStatic,
500-
value ? value.loc : loc
501-
)
502+
valueNode
502503
)
503504
)
504505
} else {
@@ -891,3 +892,17 @@ function stringifyDynamicPropNames(props: string[]): string {
891892
function isComponentTag(tag: string) {
892893
return tag[0].toLowerCase() + tag.slice(1) === 'component'
893894
}
895+
896+
function processInlineRef(
897+
bindings: BindingMetadata,
898+
raw: string
899+
): JSChildNode[] {
900+
const body = [createSimpleExpression(`_refs['${raw}'] = _value`)]
901+
const type = bindings[raw]
902+
if (type === BindingTypes.SETUP_REF) {
903+
body.push(createSimpleExpression(`${raw}.value = _value`))
904+
} else if (type === BindingTypes.SETUP_LET) {
905+
body.push(createSimpleExpression(`${raw} = _value`))
906+
}
907+
return body
908+
}

0 commit comments

Comments
 (0)