feat(v-on): cache handlers

This commit is contained in:
Evan You
2019-10-18 21:51:34 -04:00
parent 39ea67a2d2
commit 58593c4714
19 changed files with 529 additions and 243 deletions

View File

@@ -5,8 +5,7 @@ import {
ElementNode,
ObjectExpression,
CallExpression,
NodeTypes,
Property
NodeTypes
} from '@vue/compiler-core'
import { transformOn } from '../../src/transforms/vOn'
import { V_ON_WITH_MODIFIERS, V_ON_WITH_KEYS } from '../../src/runtimeHelpers'
@@ -14,10 +13,7 @@ import { transformElement } from '../../../compiler-core/src/transforms/transfor
import { transformExpression } from '../../../compiler-core/src/transforms/transformExpression'
import { createObjectMatcher } from '../../../compiler-core/__tests__/testUtils'
function parseVOnProperties(
template: string,
options: CompilerOptions = {}
): Property[] {
function parseWithVOn(template: string, options: CompilerOptions = {}) {
const ast = parse(template)
transform(ast, {
nodeTransforms: [transformExpression, transformElement],
@@ -26,13 +22,18 @@ function parseVOnProperties(
},
...options
})
return (((ast.children[0] as ElementNode).codegenNode as CallExpression)
.arguments[1] as ObjectExpression).properties
return {
root: ast,
props: (((ast.children[0] as ElementNode).codegenNode as CallExpression)
.arguments[1] as ObjectExpression).properties
}
}
describe('compiler-dom: transform v-on', () => {
it('should support multiple modifiers w/ prefixIdentifiers: true', () => {
const [prop] = parseVOnProperties(`<div @click.stop.prevent="test"/>`, {
const {
props: [prop]
} = parseWithVOn(`<div @click.stop.prevent="test"/>`, {
prefixIdentifiers: true
})
expect(prop).toMatchObject({
@@ -45,10 +46,11 @@ describe('compiler-dom: transform v-on', () => {
})
it('should support multiple modifiers and event options w/ prefixIdentifiers: true', () => {
const [prop] = parseVOnProperties(
`<div @click.stop.capture.passive="test"/>`,
{ prefixIdentifiers: true }
)
const {
props: [prop]
} = parseWithVOn(`<div @click.stop.capture.passive="test"/>`, {
prefixIdentifiers: true
})
expect(prop).toMatchObject({
type: NodeTypes.JS_PROPERTY,
value: createObjectMatcher({
@@ -59,17 +61,17 @@ describe('compiler-dom: transform v-on', () => {
options: createObjectMatcher({
capture: { content: 'true', isStatic: false },
passive: { content: 'true', isStatic: false }
}),
persistent: { content: 'true', isStatic: false }
})
})
})
})
it('should wrap keys guard for keyboard events or dynamic events', () => {
const [prop] = parseVOnProperties(
`<div @keyDown.stop.capture.ctrl.a="test"/>`,
{ prefixIdentifiers: true }
)
const {
props: [prop]
} = parseWithVOn(`<div @keyDown.stop.capture.ctrl.a="test"/>`, {
prefixIdentifiers: true
})
expect(prop).toMatchObject({
type: NodeTypes.JS_PROPERTY,
value: createObjectMatcher({
@@ -85,14 +87,15 @@ describe('compiler-dom: transform v-on', () => {
},
options: createObjectMatcher({
capture: { content: 'true', isStatic: false }
}),
persistent: { content: 'true', isStatic: false }
})
})
})
})
it('should not wrap keys guard if no key modifier is present', () => {
const [prop] = parseVOnProperties(`<div @keyup.exact="test"/>`, {
const {
props: [prop]
} = parseWithVOn(`<div @keyup.exact="test"/>`, {
prefixIdentifiers: true
})
expect(prop).toMatchObject({
@@ -105,7 +108,9 @@ describe('compiler-dom: transform v-on', () => {
})
it('should not wrap normal guard if there is only keys guard', () => {
const [prop] = parseVOnProperties(`<div @keyup.enter="test"/>`, {
const {
props: [prop]
} = parseWithVOn(`<div @keyup.enter="test"/>`, {
prefixIdentifiers: true
})
expect(prop).toMatchObject({
@@ -116,4 +121,37 @@ describe('compiler-dom: transform v-on', () => {
}
})
})
test('cache handler w/ modifiers', () => {
const {
root,
props: [prop]
} = parseWithVOn(`<div @keyup.enter.capture="foo" />`, {
prefixIdentifiers: true,
cacheHandlers: true
})
expect(root.cached).toBe(1)
// should not treat cached handler as dynamicProp, so no flags
expect((root as any).children[0].codegenNode.arguments.length).toBe(2)
expect(prop.value).toMatchObject({
type: NodeTypes.JS_CACHE_EXPRESSION,
index: 1,
value: {
type: NodeTypes.JS_OBJECT_EXPRESSION,
properties: [
{
key: { content: 'handler' },
value: {
type: NodeTypes.JS_CALL_EXPRESSION,
callee: V_ON_WITH_KEYS
}
},
{
key: { content: 'options' },
value: { type: NodeTypes.JS_OBJECT_EXPRESSION }
}
]
}
})
})
})