Skip to content

Commit

Permalink
feat(compiler): transform vOn
Browse files Browse the repository at this point in the history
  • Loading branch information
rigor789 committed Apr 1, 2020
1 parent 23b323a commit 96c93a1
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 24 deletions.

This file was deleted.

86 changes: 86 additions & 0 deletions packages/compiler/__tests__/transforms/vOn.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// todo: uncomment when vue-next#907 is released
test.todo('uncomment when vue-next#907 is released')
import {
baseParse as parse,
transform,
ElementNode,
CompilerOptions,
NodeTypes,
VNodeCall,
transformElement
} from '../../src'
import { transformOn } from '../../src/transforms/vOn'

function parseWithVOn(template: string, options: CompilerOptions = {}) {
const ast = parse(template)
transform(ast, {
nodeTransforms: [transformElement],
directiveTransforms: {
on: transformOn
},
...options
})
return {
root: ast,
node: ast.children[0] as ElementNode
}
}

describe('compiler: transform v-on', () => {
test('basic', () => {
const { node } = parseWithVOn(`<Label v-on:click="onClick"/>`)
expect((node.codegenNode as VNodeCall).props).toMatchObject({
properties: [
{
key: {
content: `onClick`,
isStatic: true,
loc: {
start: {
line: 1,
column: 13
},
end: {
line: 1,
column: 18
}
}
},
value: {
content: `onClick`,
isStatic: false,
loc: {
start: {
line: 1,
column: 20
},
end: {
line: 1,
column: 27
}
}
}
}
]
})
})

test('dynamic arg', () => {
const { node } = parseWithVOn(`<Label v-on:[event]="handler"/>`)
expect((node.codegenNode as VNodeCall).props).toMatchObject({
properties: [
{
key: {
type: NodeTypes.COMPOUND_EXPRESSION,
children: [`"on" + (`, { content: `event` }, `)`]
},
value: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `handler`,
isStatic: false
}
}
]
})
})
})
11 changes: 5 additions & 6 deletions packages/compiler/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import { parserOptions } from './parserOptions'
import { transformStyle } from './transforms/transformStyle'
// import { transformVHtml } from './transforms/vHtml'
import { transformVText } from './transforms/vText'
// import { transformModel } from './transforms/vModel'
// import { transformOn } from './transforms/vOn'
import { transformModel } from './transforms/vModel'
import { transformOn } from './transforms/vOn'
// import { transformShow } from './transforms/vShow'
// import { warnTransitionChildren } from './transforms/warnTransitionChildren'
// import { stringifyStatic } from './transforms/stringifyStatic'
Expand All @@ -28,10 +28,9 @@ export const DOMNodeTransforms: NodeTransform[] = [

export const DOMDirectiveTransforms: Record<string, DirectiveTransform> = {
cloak: noopDirectiveTransform,
// html: transformVHtml,
text: transformVText
// model: transformModel, // override compiler-core
// on: transformOn, // override compiler-core
text: transformVText,
model: transformModel, // override compiler-core todo: remove if not needed
on: transformOn // override compiler-core todo: remove if not needed
// show: transformShow
}

Expand Down
58 changes: 58 additions & 0 deletions packages/compiler/src/transforms/vOn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {
transformOn as baseTransform,
DirectiveTransform,
createObjectProperty,
createObjectExpression,
createSimpleExpression
} from '@vue/compiler-core'
import { makeMap } from '@vue/shared'

// todo: simplify - we only support `once` - no need to use makeMap
const isEventOptionModifier = /*#__PURE__*/ makeMap(`once`)

// todo: remove - no need to loop through modifiers as only `once` is supported
const generateOptionModifiers = (modifiers: string[]) => {
const eventOptionModifiers = []

for (let i = 0; i < modifiers.length; i++) {
const modifier = modifiers[i]

if (isEventOptionModifier(modifier)) {
// eventOptionModifiers: modifiers for addEventListener() options, e.g. .once
eventOptionModifiers.push(modifier)
}
}

return eventOptionModifiers
}

export const transformOn: DirectiveTransform = (dir, node, context) => {
return baseTransform(dir, node, context, baseResult => {
const { modifiers } = dir
if (!modifiers.length) return baseResult

let { key, value: handlerExp } = baseResult.props[0]
const eventOptionModifiers = generateOptionModifiers(modifiers)

if (eventOptionModifiers.length) {
handlerExp = createObjectExpression([
createObjectProperty('handler', handlerExp),
createObjectProperty(
'options',
createObjectExpression(
eventOptionModifiers.map(modifier =>
createObjectProperty(
modifier,
createSimpleExpression('true', false)
)
)
)
)
])
}

return {
props: [createObjectProperty(key, handlerExp)]
}
})
}

0 comments on commit 96c93a1

Please sign in to comment.