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', () => {
// ignore click events (has dedicated fast path)
const { node } = parseWithElementTransform(`<div @click="foo" />`, {
TemplateTextChildNode,
DirectiveArguments,
createVNodeCall,
- ConstantTypes
+ ConstantTypes,
+ JSChildNode,
+ createFunctionExpression,
+ createBlockStatement
} from '../ast'
import {
PatchFlags,
} from '../utils'
import { buildSlots } from './vSlot'
import { getConstantType } from './hoistStatic'
-import { BindingTypes } from '../options'
+import { BindingMetadata, BindingTypes } from '../options'
import {
checkCompatEnabled,
CompilerDeprecationTypes,
const prop = props[i]
if (prop.type === NodeTypes.ATTRIBUTE) {
const { loc, name, value } = prop
- let isStatic = true
+ let valueNode = createSimpleExpression(
+ value ? value.content : '',
+ true,
+ value ? value.loc : loc
+ ) as JSChildNode
if (name === 'ref') {
hasRef = true
// 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
// acrtual ref instead.
- if (
- !__BROWSER__ &&
- value &&
- context.inline &&
- context.bindingMetadata[value.content]
- ) {
- isStatic = false
+ if (!__BROWSER__ && context.inline && value?.content) {
+ valueNode = createFunctionExpression(['_value', '_refs'])
+ valueNode.body = createBlockStatement(
+ processInlineRef(context.bindingMetadata, value.content)
+ )
}
}
// skip is on <component>, or is="vue:xxx"
true,
getInnerRange(loc, 0, name.length)
),
- createSimpleExpression(
- value ? value.content : '',
- isStatic,
- value ? value.loc : loc
- )
+ valueNode
)
)
} else {
function isComponentTag(tag: string) {
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
+}