diff --git a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts
index b72533ee..138fa100 100644
--- a/packages/compiler-core/__tests__/transforms/transformElement.spec.ts
+++ b/packages/compiler-core/__tests__/transforms/transformElement.spec.ts
@@ -936,7 +936,7 @@ describe('compiler: element transform', () => {
expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_PATCH))
})
- test('the binding exists (inline ref input)', () => {
+ test('script setup inline mode template ref (binding exists)', () => {
const { node } = parseWithElementTransform(``, {
inline: true,
bindingMetadata: {
@@ -949,31 +949,30 @@ describe('compiler: element transform', () => {
{
type: NodeTypes.JS_PROPERTY,
key: {
- type: NodeTypes.SIMPLE_EXPRESSION,
+ content: 'ref_key',
+ isStatic: true
+ },
+ value: {
+ content: 'input',
+ isStatic: true
+ }
+ },
+ {
+ type: NodeTypes.JS_PROPERTY,
+ key: {
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'
- }
- ]
- }
+ content: 'input',
+ isStatic: false
}
}
]
})
})
- test('the binding not exists (inline ref input)', () => {
+ test('script setup inline mode template ref (binding does not exist)', () => {
const { node } = parseWithElementTransform(``, {
inline: true
})
@@ -983,96 +982,12 @@ describe('compiler: element transform', () => {
{
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('the binding not exists (inline maybe ref input)', () => {
- const { node } = parseWithElementTransform(``, {
- inline: true,
- bindingMetadata: {
- input: BindingTypes.SETUP_MAYBE_REF
- }
- })
- expect(node.props).toMatchObject({
- type: NodeTypes.JS_OBJECT_EXPRESSION,
- properties: [
- {
- type: NodeTypes.JS_PROPERTY,
- key: {
- type: NodeTypes.SIMPLE_EXPRESSION,
- content: 'ref',
+ content: 'input',
isStatic: true
- },
- value: {
- type: NodeTypes.JS_FUNCTION_EXPRESSION,
- params: ['_value', '_refs'],
- body: {
- type: NodeTypes.JS_BLOCK_STATEMENT,
- body: [
- {
- content: `_refs['input'] = _value`
- },
- {
- content: '_isRef(input) && (input.value = _value)'
- }
- ]
- }
- }
- }
- ]
- })
- })
-
- test('the binding not exists (inline let ref input)', () => {
- const { node } = parseWithElementTransform(``, {
- inline: true,
- bindingMetadata: {
- input: BindingTypes.SETUP_LET
- }
- })
- 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:
- '_isRef(input) ? input.value = _value : input = _value'
- }
- ]
- }
}
}
]
diff --git a/packages/compiler-core/src/compat/compatConfig.ts b/packages/compiler-core/src/compat/compatConfig.ts
index d43c441d..717b8dc4 100644
--- a/packages/compiler-core/src/compat/compatConfig.ts
+++ b/packages/compiler-core/src/compat/compatConfig.ts
@@ -20,7 +20,6 @@ export const enum CompilerDeprecationTypes {
COMPILER_V_BIND_OBJECT_ORDER = 'COMPILER_V_BIND_OBJECT_ORDER',
COMPILER_V_ON_NATIVE = 'COMPILER_V_ON_NATIVE',
COMPILER_V_IF_V_FOR_PRECEDENCE = 'COMPILER_V_IF_V_FOR_PRECEDENCE',
- COMPILER_V_FOR_REF = 'COMPILER_V_FOR_REF',
COMPILER_NATIVE_TEMPLATE = 'COMPILER_NATIVE_TEMPLATE',
COMPILER_INLINE_TEMPLATE = 'COMPILER_INLINE_TEMPLATE',
COMPILER_FILTERS = 'COMPILER_FILTER'
@@ -79,13 +78,6 @@ const deprecationData: Record = {
link: `https://v3.vuejs.org/guide/migration/v-if-v-for.html`
},
- [CompilerDeprecationTypes.COMPILER_V_FOR_REF]: {
- message:
- `Ref usage on v-for no longer creates array ref values in Vue 3. ` +
- `Consider using function refs or refactor to avoid ref usage altogether.`,
- link: `https://v3.vuejs.org/guide/migration/array-refs.html`
- },
-
[CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE]: {
message:
` with no special directives will render as a native template ` +
diff --git a/packages/compiler-core/src/transforms/transformElement.ts b/packages/compiler-core/src/transforms/transformElement.ts
index e79a560a..47cb3b0f 100644
--- a/packages/compiler-core/src/transforms/transformElement.ts
+++ b/packages/compiler-core/src/transforms/transformElement.ts
@@ -19,10 +19,7 @@ import {
TemplateTextChildNode,
DirectiveArguments,
createVNodeCall,
- ConstantTypes,
- JSChildNode,
- createFunctionExpression,
- createBlockStatement
+ ConstantTypes
} from '../ast'
import {
PatchFlags,
@@ -48,8 +45,7 @@ import {
KEEP_ALIVE,
SUSPENSE,
UNREF,
- GUARD_REACTIVE_PROPS,
- IS_REF
+ GUARD_REACTIVE_PROPS
} from '../runtimeHelpers'
import {
getInnerRange,
@@ -467,20 +463,32 @@ export function buildProps(
const prop = props[i]
if (prop.type === NodeTypes.ATTRIBUTE) {
const { loc, name, value } = prop
- let valueNode = createSimpleExpression(
- value ? value.content : '',
- true,
- value ? value.loc : loc
- ) as JSChildNode
+ let isStatic = true
if (name === 'ref') {
hasRef = true
+ if (context.scopes.vFor > 0) {
+ properties.push(
+ createObjectProperty(
+ createSimpleExpression('ref_for', true),
+ createSimpleExpression('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
// actual ref instead.
- if (!__BROWSER__ && context.inline && value?.content) {
- valueNode = createFunctionExpression(['_value', '_refs'])
- valueNode.body = createBlockStatement(
- processInlineRef(context, value.content)
+ if (
+ !__BROWSER__ &&
+ value &&
+ context.inline &&
+ context.bindingMetadata[value.content]
+ ) {
+ isStatic = false
+ properties.push(
+ createObjectProperty(
+ createSimpleExpression('ref_key', true),
+ createSimpleExpression(value.content, true, value.loc)
+ )
)
}
}
@@ -504,7 +512,11 @@ export function buildProps(
true,
getInnerRange(loc, 0, name.length)
),
- valueNode
+ createSimpleExpression(
+ value ? value.content : '',
+ isStatic,
+ value ? value.loc : loc
+ )
)
)
} else {
@@ -555,6 +567,15 @@ export function buildProps(
shouldUseBlock = true
}
+ if (isVBind && isStaticArgOf(arg, 'ref') && context.scopes.vFor > 0) {
+ properties.push(
+ createObjectProperty(
+ createSimpleExpression('ref_for', true),
+ createSimpleExpression('true')
+ )
+ )
+ }
+
// special case for v-bind and v-on with no argument
if (!arg && (isVBind || isVOn)) {
hasDynamicKeys = true
@@ -654,25 +675,6 @@ export function buildProps(
}
}
}
-
- if (
- __COMPAT__ &&
- prop.type === NodeTypes.ATTRIBUTE &&
- prop.name === 'ref' &&
- context.scopes.vFor > 0 &&
- checkCompatEnabled(
- CompilerDeprecationTypes.COMPILER_V_FOR_REF,
- context,
- prop.loc
- )
- ) {
- properties.push(
- createObjectProperty(
- createSimpleExpression('refInFor', true),
- createSimpleExpression('true', false)
- )
- )
- }
}
let propsExpression: PropsExpression | undefined = undefined
@@ -914,30 +916,3 @@ function stringifyDynamicPropNames(props: string[]): string {
function isComponentTag(tag: string) {
return tag === 'component' || tag === 'Component'
}
-
-function processInlineRef(
- context: TransformContext,
- raw: string
-): JSChildNode[] {
- const body = [createSimpleExpression(`_refs['${raw}'] = _value`)]
- const { bindingMetadata, helperString } = context
- const type = bindingMetadata[raw]
- if (type === BindingTypes.SETUP_REF) {
- body.push(createSimpleExpression(`${raw}.value = _value`))
- } else if (type === BindingTypes.SETUP_MAYBE_REF) {
- body.push(
- createSimpleExpression(
- `${helperString(IS_REF)}(${raw}) && (${raw}.value = _value)`
- )
- )
- } else if (type === BindingTypes.SETUP_LET) {
- body.push(
- createSimpleExpression(
- `${helperString(
- IS_REF
- )}(${raw}) ? ${raw}.value = _value : ${raw} = _value`
- )
- )
- }
- return body
-}
diff --git a/packages/runtime-core/__tests__/apiTemplateRef.spec.ts b/packages/runtime-core/__tests__/apiTemplateRef.spec.ts
index 2c30b58a..198687c0 100644
--- a/packages/runtime-core/__tests__/apiTemplateRef.spec.ts
+++ b/packages/runtime-core/__tests__/apiTemplateRef.spec.ts
@@ -365,4 +365,81 @@ describe('api: template refs', () => {
expect(elRef1.value).toBeNull()
expect(elRef1.value).toBe(elRef2.value)
})
+
+ // compiled output of