diff --git a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap index f5058d890..eb69bb359 100644 --- a/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/__snapshots__/compile.spec.ts.snap @@ -125,9 +125,10 @@ const t0 = _template("
{{ bar }}
") const t1 = _template("
") export function render(_ctx) { + const _component_Comp = _resolveComponent("Comp") const n0 = t0() const n3 = t1() - const n1 = _createComponent(_resolveComponent("Comp")) + const n1 = _createComponent(_component_Comp) const n2 = _createTextNode() _insert([n1, n2], n3) _renderEffect(() => _setText(n2, _ctx.bar)) diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap index 654dcd7f4..0fcf9b1e1 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/transformElement.spec.ts.snap @@ -4,7 +4,8 @@ exports[`compiler: element transform > component > do not resolve component from "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; export function render(_ctx) { - const n0 = _createComponent(_resolveComponent("Example"), null, true) + const _component_Example = _resolveComponent("Example") + const n0 = _createComponent(_component_Example, null, true) return n0 }" `; @@ -33,7 +34,8 @@ exports[`compiler: element transform > component > import + resolve component 1` "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; export function render(_ctx) { - const n0 = _createComponent(_resolveComponent("Foo"), null, true) + const _component_Foo = _resolveComponent("Foo") + const n0 = _createComponent(_component_Foo, null, true) return n0 }" `; @@ -97,7 +99,8 @@ exports[`compiler: element transform > component > should wrap as function if v- "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; export function render(_ctx) { - const n0 = _createComponent(_resolveComponent("Foo"), [{ + const _component_Foo = _resolveComponent("Foo") + const n0 = _createComponent(_component_Foo, [{ onBar: () => $event => (_ctx.handleBar($event)) }], true) return n0 @@ -108,7 +111,8 @@ exports[`compiler: element transform > component > static props 1`] = ` "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; export function render(_ctx) { - const n0 = _createComponent(_resolveComponent("Foo"), [{ + const _component_Foo = _resolveComponent("Foo") + const n0 = _createComponent(_component_Foo, [{ id: () => ("foo"), class: () => ("bar") }], true) @@ -120,7 +124,8 @@ exports[`compiler: element transform > component > v-bind="obj" 1`] = ` "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; export function render(_ctx) { - const n0 = _createComponent(_resolveComponent("Foo"), [() => (_ctx.obj)], true) + const _component_Foo = _resolveComponent("Foo") + const n0 = _createComponent(_component_Foo, [() => (_ctx.obj)], true) return n0 }" `; @@ -129,7 +134,8 @@ exports[`compiler: element transform > component > v-bind="obj" after static pro "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; export function render(_ctx) { - const n0 = _createComponent(_resolveComponent("Foo"), [{ + const _component_Foo = _resolveComponent("Foo") + const n0 = _createComponent(_component_Foo, [{ id: () => ("foo") }, () => (_ctx.obj)], true) return n0 @@ -140,7 +146,8 @@ exports[`compiler: element transform > component > v-bind="obj" before static pr "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; export function render(_ctx) { - const n0 = _createComponent(_resolveComponent("Foo"), [() => (_ctx.obj), { + const _component_Foo = _resolveComponent("Foo") + const n0 = _createComponent(_component_Foo, [() => (_ctx.obj), { id: () => ("foo") }], true) return n0 @@ -151,7 +158,8 @@ exports[`compiler: element transform > component > v-bind="obj" between static p "import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; export function render(_ctx) { - const n0 = _createComponent(_resolveComponent("Foo"), [{ + const _component_Foo = _resolveComponent("Foo") + const n0 = _createComponent(_component_Foo, [{ id: () => ("foo") }, () => (_ctx.obj), { class: () => ("bar") @@ -165,7 +173,8 @@ exports[`compiler: element transform > component > v-on="obj" 1`] = ` import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; export function render(_ctx) { - const n0 = _createComponent(_resolveComponent("Foo"), [() => (_toHandlers(_ctx.obj))], true) + const _component_Foo = _resolveComponent("Foo") + const n0 = _createComponent(_component_Foo, [() => (_toHandlers(_ctx.obj))], true) return n0 }" `; diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap index 8f3203a9e..7502b73bf 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vModel.spec.ts.snap @@ -1,5 +1,92 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`compiler: vModel transform > component > v-model for component should generate modelModifiers 1`] = ` +"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; + +export function render(_ctx) { + const _component_Comp = _resolveComponent("Comp") + const n0 = _createComponent(_component_Comp, [{ + modelValue: () => (_ctx.foo), + "onUpdate:modelValue": () => $event => (_ctx.foo = $event), + modelModifiers: () => ({ trim: true, "bar-baz": true }) + }], true) + return n0 +}" +`; + +exports[`compiler: vModel transform > component > v-model for component should work 1`] = ` +"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; + +export function render(_ctx) { + const _component_Comp = _resolveComponent("Comp") + const n0 = _createComponent(_component_Comp, [{ + modelValue: () => (_ctx.foo), + "onUpdate:modelValue": () => $event => (_ctx.foo = $event) + }], true) + return n0 +}" +`; + +exports[`compiler: vModel transform > component > v-model with arguments for component should generate modelModifiers 1`] = ` +"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; + +export function render(_ctx) { + const _component_Comp = _resolveComponent("Comp") + const n0 = _createComponent(_component_Comp, [{ + foo: () => (_ctx.foo), + "onUpdate:foo": () => $event => (_ctx.foo = $event), + fooModifiers: () => ({ trim: true }), + bar: () => (_ctx.bar), + "onUpdate:bar": () => $event => (_ctx.bar = $event), + barModifiers: () => ({ number: true }) + }], true) + return n0 +}" +`; + +exports[`compiler: vModel transform > component > v-model with arguments for component should work 1`] = ` +"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; + +export function render(_ctx) { + const _component_Comp = _resolveComponent("Comp") + const n0 = _createComponent(_component_Comp, [{ + bar: () => (_ctx.foo), + "onUpdate:bar": () => $event => (_ctx.foo = $event) + }], true) + return n0 +}" +`; + +exports[`compiler: vModel transform > component > v-model with dynamic arguments for component should generate modelModifiers 1`] = ` +"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; + +export function render(_ctx) { + const _component_Comp = _resolveComponent("Comp") + const n0 = _createComponent(_component_Comp, [{ + [_ctx.foo]: () => (_ctx.foo), + ["onUpdate:" + _ctx.foo]: () => $event => (_ctx.foo = $event), + [_ctx.foo + "Modifiers"]: () => ({ trim: true }), + [_ctx.bar]: () => (_ctx.bar), + ["onUpdate:" + _ctx.bar]: () => $event => (_ctx.bar = $event), + [_ctx.bar + "Modifiers"]: () => ({ number: true }) + }], true) + return n0 +}" +`; + +exports[`compiler: vModel transform > component > v-model with dynamic arguments for component should work 1`] = ` +"import { resolveComponent as _resolveComponent, createComponent as _createComponent } from 'vue/vapor'; + +export function render(_ctx) { + const _component_Comp = _resolveComponent("Comp") + const n0 = _createComponent(_component_Comp, [{ + [_ctx.arg]: () => (_ctx.foo), + ["onUpdate:" + _ctx.arg]: () => $event => (_ctx.foo = $event) + }], true) + return n0 +}" +`; + exports[`compiler: vModel transform > modifiers > .lazy 1`] = ` "import { vModelText as _vModelText, withDirectives as _withDirectives, delegate as _delegate, template as _template } from 'vue/vapor'; const t0 = _template("") diff --git a/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts b/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts index efe1377ca..2fa5245a9 100644 --- a/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/transformElement.spec.ts @@ -198,7 +198,7 @@ describe('compiler: element transform', () => { ) expect(code).toMatchSnapshot() - expect(code).contains('_createComponent(_resolveComponent("Foo"), [{') + expect(code).contains('_createComponent(_component_Foo, [{') expect(code).contains(' id: () => ("foo")') expect(code).contains(' class: () => ("bar")') expect(code).contains('}], true)') diff --git a/packages/compiler-vapor/__tests__/transforms/vModel.spec.ts b/packages/compiler-vapor/__tests__/transforms/vModel.spec.ts index 862f54480..80a22c880 100644 --- a/packages/compiler-vapor/__tests__/transforms/vModel.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vModel.spec.ts @@ -1,5 +1,10 @@ import { makeCompile } from './_utils' -import { transformChildren, transformElement, transformVModel } from '../../src' +import { + IRNodeTypes, + transformChildren, + transformElement, + transformVModel, +} from '../../src' import { BindingTypes, DOMErrorCodes } from '@vue/compiler-dom' const compileWithVModel = makeCompile({ @@ -198,4 +203,169 @@ describe('compiler: vModel transform', () => { expect(code).toMatchSnapshot() }) + + describe('component', () => { + test('v-model for component should work', () => { + const { code, ir } = compileWithVModel('') + expect(code).toMatchSnapshot() + expect(code).contains( + `modelValue: () => (_ctx.foo), + "onUpdate:modelValue": () => $event => (_ctx.foo = $event)`, + ) + expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.CREATE_COMPONENT_NODE, + tag: 'Comp', + props: [ + [ + { + key: { content: 'modelValue', isStatic: true }, + model: true, + modelModifiers: [], + values: [{ content: 'foo', isStatic: false }], + }, + ], + ], + }, + ]) + }) + + test('v-model with arguments for component should work', () => { + const { code, ir } = compileWithVModel('') + expect(code).toMatchSnapshot() + expect(code).contains( + `bar: () => (_ctx.foo), + "onUpdate:bar": () => $event => (_ctx.foo = $event)`, + ) + expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.CREATE_COMPONENT_NODE, + tag: 'Comp', + props: [ + [ + { + key: { content: 'bar', isStatic: true }, + model: true, + modelModifiers: [], + values: [{ content: 'foo', isStatic: false }], + }, + ], + ], + }, + ]) + }) + + test('v-model with dynamic arguments for component should work', () => { + const { code, ir } = compileWithVModel('') + expect(code).toMatchSnapshot() + expect(code).contains( + `[_ctx.arg]: () => (_ctx.foo), + ["onUpdate:" + _ctx.arg]: () => $event => (_ctx.foo = $event)`, + ) + expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.CREATE_COMPONENT_NODE, + tag: 'Comp', + props: [ + [ + { + key: { content: 'arg', isStatic: false }, + values: [{ content: 'foo', isStatic: false }], + model: true, + modelModifiers: [], + }, + ], + ], + }, + ]) + }) + + test('v-model for component should generate modelModifiers', () => { + const { code, ir } = compileWithVModel( + '', + ) + expect(code).toMatchSnapshot() + expect(code).contain( + `modelModifiers: () => ({ trim: true, "bar-baz": true })`, + ) + expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.CREATE_COMPONENT_NODE, + tag: 'Comp', + props: [ + [ + { + key: { content: 'modelValue', isStatic: true }, + values: [{ content: 'foo', isStatic: false }], + model: true, + modelModifiers: ['trim', 'bar-baz'], + }, + ], + ], + }, + ]) + }) + + test('v-model with arguments for component should generate modelModifiers', () => { + const { code, ir } = compileWithVModel( + '', + ) + expect(code).toMatchSnapshot() + expect(code).contain(`fooModifiers: () => ({ trim: true })`) + expect(code).contain(`barModifiers: () => ({ number: true })`) + expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.CREATE_COMPONENT_NODE, + tag: 'Comp', + props: [ + [ + { + key: { content: 'foo', isStatic: true }, + values: [{ content: 'foo', isStatic: false }], + model: true, + modelModifiers: ['trim'], + }, + { + key: { content: 'bar', isStatic: true }, + values: [{ content: 'bar', isStatic: false }], + model: true, + modelModifiers: ['number'], + }, + ], + ], + }, + ]) + }) + + test('v-model with dynamic arguments for component should generate modelModifiers ', () => { + const { code, ir } = compileWithVModel( + '', + ) + expect(code).toMatchSnapshot() + expect(code).contain(`[_ctx.foo + "Modifiers"]: () => ({ trim: true })`) + expect(code).contain(`[_ctx.bar + "Modifiers"]: () => ({ number: true })`) + expect(ir.block.operation).toMatchObject([ + { + type: IRNodeTypes.CREATE_COMPONENT_NODE, + tag: 'Comp', + props: [ + [ + { + key: { content: 'foo', isStatic: false }, + values: [{ content: 'foo', isStatic: false }], + model: true, + modelModifiers: ['trim'], + }, + { + key: { content: 'bar', isStatic: false }, + values: [{ content: 'bar', isStatic: false }], + model: true, + modelModifiers: ['number'], + }, + ], + ], + }, + ]) + }) + }) }) diff --git a/packages/compiler-vapor/src/generate.ts b/packages/compiler-vapor/src/generate.ts index d30274f5d..bd36453d8 100644 --- a/packages/compiler-vapor/src/generate.ts +++ b/packages/compiler-vapor/src/generate.ts @@ -125,7 +125,7 @@ export function generate( } push(INDENT_START) - push(...genBlockContent(ir.block, context)) + push(...genBlockContent(ir.block, context, true)) push(INDENT_END, NEWLINE) if (isSetupInlined) { diff --git a/packages/compiler-vapor/src/generators/block.ts b/packages/compiler-vapor/src/generators/block.ts index e24e7961f..4ed4e00d4 100644 --- a/packages/compiler-vapor/src/generators/block.ts +++ b/packages/compiler-vapor/src/generators/block.ts @@ -10,6 +10,7 @@ import { INDENT_START, NEWLINE, buildCodeFragment, + genCall, } from './utils' import type { CodegenContext } from '../generate' import { genWithDirective } from './directive' @@ -21,6 +22,7 @@ export function genBlock( oper: BlockIRNode, context: CodegenContext, args: CodeFragment[] = [], + root?: boolean, customReturns?: (returns: CodeFragment[]) => CodeFragment[], ): CodeFragment[] { return [ @@ -28,7 +30,7 @@ export function genBlock( ...args, ') => {', INDENT_START, - ...genBlockContent(oper, context, customReturns), + ...genBlockContent(oper, context, root, customReturns), INDENT_END, NEWLINE, '}', @@ -38,10 +40,23 @@ export function genBlock( export function genBlockContent( { dynamic, effect, operation, returns }: BlockIRNode, context: CodegenContext, + root?: boolean, customReturns?: (returns: CodeFragment[]) => CodeFragment[], ): CodeFragment[] { const [frag, push] = buildCodeFragment() + if (root) + for (const name of context.ir.component) { + push( + NEWLINE, + `const _component_${name} = `, + ...genCall( + context.vaporHelper('resolveComponent'), + JSON.stringify(name), + ), + ) + } + for (const child of dynamic.children) { push(...genChildren(child, context, child.id!)) } diff --git a/packages/compiler-vapor/src/generators/component.ts b/packages/compiler-vapor/src/generators/component.ts index ec9b9064e..34d349d41 100644 --- a/packages/compiler-vapor/src/generators/component.ts +++ b/packages/compiler-vapor/src/generators/component.ts @@ -1,4 +1,4 @@ -import { extend, isArray } from '@vue/shared' +import { camelize, extend, isArray } from '@vue/shared' import type { CodegenContext } from '../generate' import type { CreateComponentIRNode, IRProp } from '../ir' import { @@ -13,6 +13,8 @@ import { genExpression } from './expression' import { genPropKey } from './prop' import { createSimpleExpression } from '@vue/compiler-dom' import { genEventHandler } from './event' +import { genDirectiveModifiers } from './directive' +import { genModelHandler } from './modelValue' // TODO: generate component slots export function genCreateComponent( @@ -23,7 +25,7 @@ export function genCreateComponent( const tag = genTag() const isRoot = oper.root - const props = genProps() + const rawProps = genRawProps() return [ NEWLINE, @@ -31,14 +33,14 @@ export function genCreateComponent( ...genCall( vaporHelper('createComponent'), tag, - props || (isRoot ? 'null' : false), + rawProps || (isRoot ? 'null' : false), isRoot && 'true', ), ] function genTag() { if (oper.resolve) { - return genCall(vaporHelper('resolveComponent'), JSON.stringify(oper.tag)) + return [`_component_${oper.tag}`] } else { return genExpression( extend(createSimpleExpression(oper.tag, false), { ast: null }), @@ -47,11 +49,11 @@ export function genCreateComponent( } } - function genProps() { + function genRawProps() { const props = oper.props .map(props => { if (isArray(props)) { - if (!props.length) return undefined + if (!props.length) return return genStaticProps(props) } else { let expr = genExpression(props.value, context) @@ -79,8 +81,34 @@ export function genCreateComponent( ...(prop.handler ? genEventHandler(context, prop.values[0]) : ['() => (', ...genExpression(prop.values[0], context), ')']), + ...(prop.model + ? [...genModelEvent(prop), ...genModelModifiers(prop)] + : []), ] }), ) + + function genModelEvent(prop: IRProp): CodeFragment[] { + const name = prop.key.isStatic + ? [JSON.stringify(`onUpdate:${camelize(prop.key.content)}`)] + : ['["onUpdate:" + ', ...genExpression(prop.key, context), ']'] + const handler = genModelHandler(prop.values[0], context) + + return [',', NEWLINE, ...name, ': ', ...handler] + } + + function genModelModifiers(prop: IRProp): CodeFragment[] { + const { key, modelModifiers } = prop + if (!modelModifiers || !modelModifiers.length) return [] + + const modifiersKey = key.isStatic + ? key.content === 'modelValue' + ? [`modelModifiers`] + : [`${key.content}Modifiers`] + : ['[', ...genExpression(key, context), ' + "Modifiers"]'] + + const modifiersVal = genDirectiveModifiers(modelModifiers) + return [',', NEWLINE, ...modifiersKey, `: () => ({ ${modifiersVal} })`] + } } } diff --git a/packages/compiler-vapor/src/generators/directive.ts b/packages/compiler-vapor/src/generators/directive.ts index 6dcbef50c..452b79f9d 100644 --- a/packages/compiler-vapor/src/generators/directive.ts +++ b/packages/compiler-vapor/src/generators/directive.ts @@ -35,7 +35,7 @@ export function genWithDirective( ? NULL : false const modifiers = dir.modifiers.length - ? ['{ ', genDirectiveModifiers(), ' }'] + ? ['{ ', genDirectiveModifiers(dir.modifiers), ' }'] : false return genMulti(['[', ']', ', '], directive, value, argument, modifiers) @@ -61,14 +61,14 @@ export function genWithDirective( } } } - - function genDirectiveModifiers() { - return dir.modifiers - .map( - value => - `${isSimpleIdentifier(value) ? value : JSON.stringify(value)}: true`, - ) - .join(', ') - } } } + +export function genDirectiveModifiers(modifiers: string[]) { + return modifiers + .map( + value => + `${isSimpleIdentifier(value) ? value : JSON.stringify(value)}: true`, + ) + .join(', ') +} diff --git a/packages/compiler-vapor/src/generators/for.ts b/packages/compiler-vapor/src/generators/for.ts index 6dc1aca7b..96eef4067 100644 --- a/packages/compiler-vapor/src/generators/for.ts +++ b/packages/compiler-vapor/src/generators/for.ts @@ -42,7 +42,7 @@ export function genFor( ] const blockFn = context.withId( - () => genBlock(render, context, ['_block'], blockReturns), + () => genBlock(render, context, ['_block'], false, blockReturns), idMap, ) diff --git a/packages/compiler-vapor/src/generators/modelValue.ts b/packages/compiler-vapor/src/generators/modelValue.ts index fec871391..2a3ab4cda 100644 --- a/packages/compiler-vapor/src/generators/modelValue.ts +++ b/packages/compiler-vapor/src/generators/modelValue.ts @@ -3,28 +3,36 @@ import { genExpression } from './expression' import type { SetModelValueIRNode } from '../ir' import type { CodegenContext } from '../generate' import { type CodeFragment, NEWLINE, genCall } from './utils' +import type { SimpleExpressionNode } from '@vue/compiler-dom' export function genSetModelValue( oper: SetModelValueIRNode, context: CodegenContext, ): CodeFragment[] { - const { - vaporHelper, - - options: { isTS }, - } = context - + const { vaporHelper } = context const name = oper.key.isStatic ? [JSON.stringify(`update:${camelize(oper.key.content)}`)] : ['`update:${', ...genExpression(oper.key, context), '}`'] - const handler = [ - `() => ${isTS ? `($event: any)` : `$event`} => (`, - ...genExpression(oper.value, context, '$event'), - ')', - ] + + const handler = genModelHandler(oper.value, context) return [ NEWLINE, ...genCall(vaporHelper('delegate'), `n${oper.element}`, name, handler), ] } + +export function genModelHandler( + value: SimpleExpressionNode, + context: CodegenContext, +) { + const { + options: { isTS }, + } = context + + return [ + `() => ${isTS ? `($event: any)` : `$event`} => (`, + ...genExpression(value, context, '$event'), + ')', + ] +} diff --git a/packages/compiler-vapor/src/ir.ts b/packages/compiler-vapor/src/ir.ts index af8f36de3..e3f0284f2 100644 --- a/packages/compiler-vapor/src/ir.ts +++ b/packages/compiler-vapor/src/ir.ts @@ -57,6 +57,7 @@ export interface RootIRNode { node: RootNode source: string template: string[] + component: Set block: BlockIRNode } diff --git a/packages/compiler-vapor/src/transform.ts b/packages/compiler-vapor/src/transform.ts index b00069fbd..bc2de550a 100644 --- a/packages/compiler-vapor/src/transform.ts +++ b/packages/compiler-vapor/src/transform.ts @@ -44,6 +44,8 @@ export interface DirectiveTransformResult { modifier?: '.' | '^' runtimeCamelize?: boolean handler?: boolean + model?: boolean + modelModifiers?: string[] } // A structural directive transform is technically also a NodeTransform; @@ -75,6 +77,8 @@ export interface TransformContext { inVOnce: boolean inVFor: number + component: Set + enterBlock(ir: TransformContext['block'], isVFor?: boolean): () => void reference(): number increaseId(): number @@ -147,6 +151,7 @@ function createRootContext( inVOnce: false, inVFor: 0, comment: [], + component: root.component, increaseId: () => globalId++, reference() { @@ -211,6 +216,7 @@ export function transform( node: root, source: root.source, template: [], + component: new Set(), block: { type: IRNodeTypes.BLOCK, node: root, diff --git a/packages/compiler-vapor/src/transforms/transformElement.ts b/packages/compiler-vapor/src/transforms/transformElement.ts index 1c627a86d..7c51bb6a5 100644 --- a/packages/compiler-vapor/src/transforms/transformElement.ts +++ b/packages/compiler-vapor/src/transforms/transformElement.ts @@ -86,6 +86,9 @@ function transformComponentElement( } } } + if (resolve) { + context.component.add(tag) + } context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERT const root = diff --git a/packages/compiler-vapor/src/transforms/vModel.ts b/packages/compiler-vapor/src/transforms/vModel.ts index 8831db92d..72382ffb4 100644 --- a/packages/compiler-vapor/src/transforms/vModel.ts +++ b/packages/compiler-vapor/src/transforms/vModel.ts @@ -65,6 +65,12 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => { let runtimeDirective: VaporHelper | undefined if (isComponent) { + return { + key: arg ? arg : createSimpleExpression('modelValue', true), + value: exp, + model: true, + modelModifiers: dir.modifiers, + } } else { if (dir.arg) context.options.onError(