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(