feat(compiler-core/v-model): avoid patching v-model handler when possible

This commit is contained in:
Evan You
2019-10-16 13:56:00 -04:00
parent 48b79d02e8
commit 5481f76ce8
4 changed files with 102 additions and 21 deletions

View File

@@ -8,7 +8,7 @@ export default function render() {
return (openBlock(), createBlock(\\"input\\", {
modelValue: _ctx.model[_ctx.index],
\\"onUpdate:modelValue\\": $event => (_ctx.model[_ctx.index] = $event)
}, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
}, null, 8 /* PROPS */, [\\"modelValue\\"]))
}"
`;
@@ -35,7 +35,7 @@ export default function render() {
return (openBlock(), createBlock(\\"input\\", {
modelValue: _ctx.model,
\\"onUpdate:modelValue\\": $event => (_ctx.model = $event)
}, null, 8 /* PROPS */, [\\"modelValue\\", \\"onUpdate:modelValue\\"]))
}, null, 8 /* PROPS */, [\\"modelValue\\"]))
}"
`;

View File

@@ -5,18 +5,29 @@ import {
ElementNode,
ObjectExpression,
CompilerOptions,
CallExpression
CallExpression,
ForNode,
PlainElementNode,
PlainElementCodegenNode,
ComponentNode
} from '../../src'
import { ErrorCodes } from '../../src/errors'
import { transformModel } from '../../src/transforms/vModel'
import { transformElement } from '../../src/transforms/transformElement'
import { transformExpression } from '../../src/transforms/transformExpression'
import { transformFor } from '../../src/transforms/vFor'
import { trackSlotScopes } from '../../src/transforms/vSlot'
function parseWithVModel(template: string, options: CompilerOptions = {}) {
const ast = parse(template)
transform(ast, {
nodeTransforms: [transformExpression, transformElement],
nodeTransforms: [
transformFor,
transformExpression,
trackSlotScopes,
transformElement
],
directiveTransforms: {
...options.directiveTransforms,
model: transformModel
@@ -327,6 +338,39 @@ describe('compiler: transform v-model', () => {
expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()
})
test('should not mark update handler dynamic', () => {
const root = parseWithVModel('<input v-model="foo" />', {
prefixIdentifiers: true
})
const codegen = (root.children[0] as PlainElementNode)
.codegenNode as PlainElementCodegenNode
expect(codegen.arguments[4]).toBe(`["modelValue"]`)
})
test('should mark update handler dynamic if it refers v-for scope variables', () => {
const root = parseWithVModel(
'<input v-for="i in list" v-model="foo[i]" />',
{
prefixIdentifiers: true
}
)
const codegen = ((root.children[0] as ForNode)
.children[0] as PlainElementNode).codegenNode as PlainElementCodegenNode
expect(codegen.arguments[4]).toBe(`["modelValue", "onUpdate:modelValue"]`)
})
test('should mark update handler dynamic if it refers slot scope variables', () => {
const root = parseWithVModel(
'<Comp v-slot="{ foo }"><input v-model="foo"/></Comp>',
{
prefixIdentifiers: true
}
)
const codegen = ((root.children[0] as ComponentNode)
.children[0] as PlainElementNode).codegenNode as PlainElementCodegenNode
expect(codegen.arguments[4]).toBe(`["modelValue", "onUpdate:modelValue"]`)
})
describe('errors', () => {
test('missing expression', () => {
const onError = jest.fn()