event modifiers

This commit is contained in:
Evan You 2016-04-12 17:00:29 -04:00
parent e577a1aa3c
commit c8c96a4248
4 changed files with 71 additions and 42 deletions

View File

@ -1,35 +1,61 @@
import { isArray } from '../../util/index'
const simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?'\]|\[".*?"\]|\[\d+\]|\[[A-Za-z_$][\w$]*\])*$/
const modifierCode = {
stop: '$event.stopPropagation();',
prevent: '$event.preventDefault();',
self: 'if($event.target !== $event.currentTarget)return;'
}
export function addHandler (events, name, value) {
export function addHandler (events, name, value, modifiers) {
// check capture modifier
const captureIndex = modifiers && modifiers.indexOf('capture')
if (captureIndex > -1) {
modifiers.splice(captureIndex, 1)
name = '!' + name // mark the event as captured
}
const newHandler = { value, modifiers }
const handlers = events[name]
if (isArray(handlers)) {
handlers.push(value)
handlers.push(newHandler)
} else if (handlers) {
events[name] = [handlers, value]
events[name] = [handlers, newHandler]
} else {
events[name] = value
events[name] = newHandler
}
}
export function genEvents (events) {
let res = 'on:{'
for (var name in events) {
for (let name in events) {
res += `"${name}":${genHandler(events[name])},`
}
console.log(res)
return res.slice(0, -1) + '}'
}
function genHandler (value) {
// TODO support modifiers
if (!value) {
function genHandler (handler) {
if (!handler) {
return `function(){}`
} else if (isArray(value)) {
return `[${value.map(genHandler).join(',')}]`
} else if (simplePathRE.test(value)) {
return value
} else if (isArray(handler)) {
return `[${handler.map(genHandler).join(',')}]`
} else if (!handler.modifiers || !handler.modifiers.length) {
return simplePathRE.test(handler.value)
? handler.value
: `function($event){${handler.value}}`
} else {
return `function($event){${value}}`
let code = 'function($event){'
for (let i = 0; i < handler.modifiers.length; i++) {
let modifier = handler.modifiers[i]
code += modifierCode[modifier] || genKeyFilter(modifier)
}
let handlerCode = simplePathRE.test(handler.value)
? handler.value + '()'
: handler.value
return code + handlerCode + '}'
}
}
function genKeyFilter (key) {
}

View File

@ -15,15 +15,10 @@ export function getAndRemoveAttr (el, attr) {
const modifierRE = /\.[^\.]+/g
export function parseModifiers (name) {
var res = Object.create(null)
var match = name.match(modifierRE)
const match = name.match(modifierRE)
if (match) {
var i = match.length
while (i--) {
res[match[i].slice(1)] = true
}
return match.map(m => m.slice(1))
}
return res
}
export function removeModifiers (name) {

View File

@ -8,9 +8,9 @@ import {
getAndRemoveAttr
} from './helpers'
const dirRE = /^v-|^@|^:/
const bindRE = /^:|^v-bind:/
const onRE = /^@|^v-on:/
const dirRE = /^v-/
const mustUsePropsRE = /^(value|selected|checked|muted)$/
export function generate (ast) {
@ -90,26 +90,32 @@ function genData (el, key) {
let attr = el.attrs[i]
let name = attr.name
let value = attr.value
if (bindRE.test(name)) {
name = name.replace(bindRE, '')
if (name === 'style') {
data += `style: ${value},`
} else if (mustUsePropsRE.test(name)) {
hasProps = true
props += `"${name}": (${value}),`
if (dirRE.test(name)) {
// modifiers
const modifiers = parseModifiers(name)
name = removeModifiers(name)
if (bindRE.test(name)) {
name = name.replace(bindRE, '')
if (name === 'style') {
data += `style: ${value},`
} else if (mustUsePropsRE.test(name)) {
hasProps = true
props += `"${name}": (${value}),`
} else {
hasAttrs = true
attrs += `"${name}": (${value}),`
}
} else if (onRE.test(name)) {
hasEvents = true
name = name.replace(onRE, '')
addHandler(events, name, value, modifiers)
} else if (name === 'v-model') {
hasProps = hasEvents = true
props += genModel(el, events, value) + ','
} else {
hasAttrs = true
attrs += `"${name}": (${value}),`
// TODO: normal directives
}
} else if (onRE.test(name)) {
hasEvents = true
name = name.replace(onRE, '')
addHandler(events, name, value)
} else if (name === 'v-model') {
hasProps = hasEvents = true
props += genModel(el, events, value) + ','
} else if (dirRE.test(name)) {
// TODO: normal directives
} else {
hasAttrs = true
attrs += `"${name}": (${JSON.stringify(attr.value)}),`

View File

@ -12,7 +12,7 @@ function fnInvoker(o) {
}
function updateEventListeners(oldVnode, vnode) {
let name, cur, old
let name, cur, old, event, capture
const elm = vnode.elm
const oldOn = oldVnode.data.on || {}
const on = vnode.data.on
@ -21,12 +21,14 @@ function updateEventListeners(oldVnode, vnode) {
cur = on[name]
old = oldOn[name]
if (old === undefined) {
capture = name.charAt(0) === '!'
event = capture ? name.slice(1) : name
if (Array.isArray(cur)) {
elm.addEventListener(name, arrInvoker(cur))
elm.addEventListener(event, arrInvoker(cur), capture)
} else {
cur = {fn: cur}
on[name] = cur
elm.addEventListener(name, fnInvoker(cur))
elm.addEventListener(event, fnInvoker(cur), capture)
}
} else if (Array.isArray(old)) {
// Deliberately modify old array since it's captured in closure created with `arrInvoker`