fix(compiler): generate function ref for script setup if inline is ture. (#4492)

This commit is contained in:
ygj6 2021-09-02 23:27:20 +08:00 committed by GitHub
parent 85807967dc
commit 4cd282b0a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 98 additions and 15 deletions

View File

@ -936,6 +936,74 @@ describe('compiler: element transform', () => {
expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_PATCH)) expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_PATCH))
}) })
test('the binding exists (inline ref input)', () => {
const { node } = parseWithElementTransform(`<input ref="input"/>`, {
inline: true,
bindingMetadata: {
input: BindingTypes.SETUP_REF
}
})
expect(node.props).toMatchObject({
type: NodeTypes.JS_OBJECT_EXPRESSION,
properties: [
{
type: NodeTypes.JS_PROPERTY,
key: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'ref',
isStatic: true
},
value: {
type: NodeTypes.JS_FUNCTION_EXPRESSION,
params: ['_value', '_refs'],
body: {
type: NodeTypes.JS_BLOCK_STATEMENT,
body: [
{
content: `_refs['input'] = _value`
},
{
content: 'input.value = _value'
}
]
}
}
}
]
})
})
test('the binding not exists (inline ref input)', () => {
const { node } = parseWithElementTransform(`<input ref="input"/>`, {
inline: true
})
expect(node.props).toMatchObject({
type: NodeTypes.JS_OBJECT_EXPRESSION,
properties: [
{
type: NodeTypes.JS_PROPERTY,
key: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: 'ref',
isStatic: true
},
value: {
type: NodeTypes.JS_FUNCTION_EXPRESSION,
params: ['_value', '_refs'],
body: {
type: NodeTypes.JS_BLOCK_STATEMENT,
body: [
{
content: `_refs['input'] = _value`
}
]
}
}
}
]
})
})
test('HYDRATE_EVENTS', () => { test('HYDRATE_EVENTS', () => {
// ignore click events (has dedicated fast path) // ignore click events (has dedicated fast path)
const { node } = parseWithElementTransform(`<div @click="foo" />`, { const { node } = parseWithElementTransform(`<div @click="foo" />`, {

View File

@ -19,7 +19,10 @@ import {
TemplateTextChildNode, TemplateTextChildNode,
DirectiveArguments, DirectiveArguments,
createVNodeCall, createVNodeCall,
ConstantTypes ConstantTypes,
JSChildNode,
createFunctionExpression,
createBlockStatement
} from '../ast' } from '../ast'
import { import {
PatchFlags, PatchFlags,
@ -58,7 +61,7 @@ import {
} from '../utils' } from '../utils'
import { buildSlots } from './vSlot' import { buildSlots } from './vSlot'
import { getConstantType } from './hoistStatic' import { getConstantType } from './hoistStatic'
import { BindingTypes } from '../options' import { BindingMetadata, BindingTypes } from '../options'
import { import {
checkCompatEnabled, checkCompatEnabled,
CompilerDeprecationTypes, CompilerDeprecationTypes,
@ -459,19 +462,21 @@ export function buildProps(
const prop = props[i] const prop = props[i]
if (prop.type === NodeTypes.ATTRIBUTE) { if (prop.type === NodeTypes.ATTRIBUTE) {
const { loc, name, value } = prop const { loc, name, value } = prop
let isStatic = true let valueNode = createSimpleExpression(
value ? value.content : '',
true,
value ? value.loc : loc
) as JSChildNode
if (name === 'ref') { if (name === 'ref') {
hasRef = true hasRef = true
// in inline mode there is no setupState object, so we can't use string // 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 // keys to set the ref. Instead, we need to transform it to pass the
// acrtual ref instead. // acrtual ref instead.
if ( if (!__BROWSER__ && context.inline && value?.content) {
!__BROWSER__ && valueNode = createFunctionExpression(['_value', '_refs'])
value && valueNode.body = createBlockStatement(
context.inline && processInlineRef(context.bindingMetadata, value.content)
context.bindingMetadata[value.content] )
) {
isStatic = false
} }
} }
// skip is on <component>, or is="vue:xxx" // skip is on <component>, or is="vue:xxx"
@ -494,11 +499,7 @@ export function buildProps(
true, true,
getInnerRange(loc, 0, name.length) getInnerRange(loc, 0, name.length)
), ),
createSimpleExpression( valueNode
value ? value.content : '',
isStatic,
value ? value.loc : loc
)
) )
) )
} else { } else {
@ -891,3 +892,17 @@ function stringifyDynamicPropNames(props: string[]): string {
function isComponentTag(tag: string) { function isComponentTag(tag: string) {
return tag[0].toLowerCase() + tag.slice(1) === 'component' return tag[0].toLowerCase() + tag.slice(1) === 'component'
} }
function processInlineRef(
bindings: BindingMetadata,
raw: string
): JSChildNode[] {
const body = [createSimpleExpression(`_refs['${raw}'] = _value`)]
const type = bindings[raw]
if (type === BindingTypes.SETUP_REF) {
body.push(createSimpleExpression(`${raw}.value = _value`))
} else if (type === BindingTypes.SETUP_LET) {
body.push(createSimpleExpression(`${raw} = _value`))
}
return body
}