mirror of https://github.com/vuejs/core.git
refactor(compiler-vapor): v-on
This commit is contained in:
parent
45e86e36d7
commit
da8e196ca5
|
@ -152,11 +152,17 @@ export const isMemberExpressionBrowser = (path: string): boolean => {
|
|||
}
|
||||
|
||||
export const isMemberExpressionNode = __BROWSER__
|
||||
? (NOOP as any as (path: string, context: TransformContext) => boolean)
|
||||
: (path: string, context: TransformContext): boolean => {
|
||||
? (NOOP as any as (
|
||||
path: string,
|
||||
options: Pick<TransformContext, 'expressionPlugins'>
|
||||
) => boolean)
|
||||
: (
|
||||
path: string,
|
||||
options: Pick<TransformContext, 'expressionPlugins'>
|
||||
): boolean => {
|
||||
try {
|
||||
let ret: Expression = parseExpression(path, {
|
||||
plugins: context.expressionPlugins
|
||||
plugins: options.expressionPlugins
|
||||
})
|
||||
if (ret.type === 'TSAsExpression' || ret.type === 'TSTypeAssertion') {
|
||||
ret = ret.expression
|
||||
|
|
|
@ -438,31 +438,48 @@ function genSetEvent(oper: SetEventIRNode, context: CodegenContext) {
|
|||
const { vaporHelper, push, pushWithNewline } = context
|
||||
|
||||
pushWithNewline(`${vaporHelper('on')}(n${oper.element}, `)
|
||||
// second arg: event name
|
||||
genExpression(oper.key, context)
|
||||
|
||||
// 2nd arg: event name
|
||||
if (oper.keyOverride) {
|
||||
const find = JSON.stringify(oper.keyOverride[0])
|
||||
const replacement = JSON.stringify(oper.keyOverride[1])
|
||||
push('(')
|
||||
genExpression(oper.key, context)
|
||||
push(`) === ${find} ? ${replacement} : (`)
|
||||
genExpression(oper.key, context)
|
||||
push(')')
|
||||
} else {
|
||||
genExpression(oper.key, context)
|
||||
}
|
||||
push(', ')
|
||||
|
||||
const { keys, nonKeys, options } = oper.modifiers
|
||||
if (keys.length) {
|
||||
push(`${vaporHelper('withKeys')}(`)
|
||||
}
|
||||
if (nonKeys.length) {
|
||||
push(`${vaporHelper('withModifiers')}(`)
|
||||
|
||||
// 3rd arg: event handler
|
||||
if (oper.value && oper.value.content.trim()) {
|
||||
if (keys.length) {
|
||||
push(`${vaporHelper('withKeys')}(`)
|
||||
}
|
||||
if (nonKeys.length) {
|
||||
push(`${vaporHelper('withModifiers')}(`)
|
||||
}
|
||||
push('(...args) => (')
|
||||
genExpression(oper.value, context)
|
||||
push(' && ')
|
||||
genExpression(oper.value, context)
|
||||
push('(...args))')
|
||||
|
||||
if (nonKeys.length) {
|
||||
push(`, ${genArrayExpression(nonKeys)})`)
|
||||
}
|
||||
if (keys.length) {
|
||||
push(`, ${genArrayExpression(keys)})`)
|
||||
}
|
||||
} else {
|
||||
push('() => {}')
|
||||
}
|
||||
|
||||
// gen event handler
|
||||
push('(...args) => (')
|
||||
genExpression(oper.value, context)
|
||||
push(' && ')
|
||||
genExpression(oper.value, context)
|
||||
push('(...args))')
|
||||
|
||||
if (nonKeys.length) {
|
||||
push(`, ${genArrayExpression(nonKeys)})`)
|
||||
}
|
||||
if (keys.length) {
|
||||
push(`, ${genArrayExpression(keys)})`)
|
||||
}
|
||||
// 4th arg, gen options
|
||||
if (options.length) {
|
||||
push(`, { ${options.map((v) => `${v}: true`).join(', ')} }`)
|
||||
}
|
||||
|
|
|
@ -69,11 +69,12 @@ export interface SetTextIRNode extends BaseIRNode {
|
|||
value: IRExpression
|
||||
}
|
||||
|
||||
export type KeyOverride = [find: string, replacement: string]
|
||||
export interface SetEventIRNode extends BaseIRNode {
|
||||
type: IRNodeTypes.SET_EVENT
|
||||
element: number
|
||||
key: IRExpression
|
||||
value: IRExpression
|
||||
value?: SimpleExpressionNode
|
||||
modifiers: {
|
||||
// modifiers for addEventListener() options, e.g. .passive & .capture
|
||||
options: string[]
|
||||
|
@ -82,6 +83,7 @@ export interface SetEventIRNode extends BaseIRNode {
|
|||
// modifiers that needs runtime guards, withModifiers
|
||||
nonKeys: string[]
|
||||
}
|
||||
keyOverride?: KeyOverride
|
||||
}
|
||||
|
||||
export interface SetHtmlIRNode extends BaseIRNode {
|
||||
|
|
|
@ -1,70 +1,64 @@
|
|||
import {
|
||||
createCompilerError,
|
||||
createSimpleExpression,
|
||||
ErrorCodes,
|
||||
ExpressionNode,
|
||||
isStaticExp,
|
||||
NodeTypes,
|
||||
} from '@vue/compiler-core'
|
||||
import { createCompilerError, ErrorCodes } from '@vue/compiler-core'
|
||||
import type { DirectiveTransform } from '../transform'
|
||||
import { IRNodeTypes } from '../ir'
|
||||
import { IRNodeTypes, KeyOverride } from '../ir'
|
||||
import { resolveModifiers } from '@vue/compiler-dom'
|
||||
|
||||
export const transformVOn: DirectiveTransform = (dir, node, context) => {
|
||||
const { arg, exp, loc, modifiers } = dir
|
||||
let { arg, exp, loc, modifiers } = dir
|
||||
if (!exp && !modifiers.length) {
|
||||
context.options.onError(
|
||||
createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (!arg) {
|
||||
// TODO support v-on="{}"
|
||||
return
|
||||
} else if (exp === undefined) {
|
||||
// TODO X_V_ON_NO_EXPRESSION error
|
||||
return
|
||||
}
|
||||
|
||||
const handlerKey = `on${arg.content}`
|
||||
const { keyModifiers, nonKeyModifiers, eventOptionModifiers } =
|
||||
resolveModifiers(handlerKey, modifiers, null, loc)
|
||||
resolveModifiers(
|
||||
arg.isStatic ? `on${arg.content}` : arg,
|
||||
modifiers,
|
||||
null,
|
||||
loc,
|
||||
)
|
||||
|
||||
let keyOverride: KeyOverride | undefined
|
||||
|
||||
// normalize click.right and click.middle since they don't actually fire
|
||||
let name = arg.content
|
||||
|
||||
const isStaticClick = arg.isStatic && arg.content.toLowerCase() === 'click'
|
||||
|
||||
if (nonKeyModifiers.includes('right')) {
|
||||
name = transformClick(arg, 'contextmenu')
|
||||
if (isStaticClick) {
|
||||
arg = { ...arg, content: 'contextmenu' }
|
||||
} else if (!arg.isStatic) {
|
||||
keyOverride = ['click', 'contextmenu']
|
||||
}
|
||||
}
|
||||
if (nonKeyModifiers.includes('middle')) {
|
||||
name = transformClick(arg, 'mouseup')
|
||||
if (keyOverride) {
|
||||
// TODO error here
|
||||
}
|
||||
if (isStaticClick) {
|
||||
arg = { ...arg, content: 'mouseup' }
|
||||
} else if (!arg.isStatic) {
|
||||
keyOverride = ['click', 'mouseup']
|
||||
}
|
||||
}
|
||||
|
||||
// TODO reactive
|
||||
context.registerOperation({
|
||||
type: IRNodeTypes.SET_EVENT,
|
||||
loc,
|
||||
element: context.reference(),
|
||||
key: createSimpleExpression(name, true, arg.loc),
|
||||
key: arg,
|
||||
value: exp,
|
||||
modifiers: {
|
||||
keys: keyModifiers,
|
||||
nonKeys: nonKeyModifiers,
|
||||
options: eventOptionModifiers,
|
||||
},
|
||||
keyOverride,
|
||||
})
|
||||
}
|
||||
|
||||
function transformClick(key: ExpressionNode, event: string) {
|
||||
const isStaticClick =
|
||||
isStaticExp(key) && key.content.toLowerCase() === 'click'
|
||||
|
||||
if (isStaticClick) {
|
||||
return event
|
||||
} else if (key.type !== NodeTypes.SIMPLE_EXPRESSION) {
|
||||
// TODO: handle CompoundExpression
|
||||
return 'TODO'
|
||||
} else {
|
||||
return key.content.toLowerCase()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue