几种常见的写法
@click="fn"
@click=" ** = arguments[0] + arguments[1]"
@click=" ** = $event"
methods: { fn(){ arguments[0] .... } }
$events 与 arguments 的区别在哪呢?
答案是:$events = arguments[0].
下面是解析v-on内容到执行内容的大概步骤:
- parser/index.js 解析html中绑定的v-on
function processAttrs() {
...
else if (onRE.test(name)) { // v-on
name = name.replace(onRE, '')
addHandler(el, name, value, modifiers, false, warn)
}
...
}
- complile/helpers.js 将事件加入到el.events
function addHandler() {
....
const handlers = events[name]
/* istanbul ignore if */
if (Array.isArray(handlers)) {
important ? handlers.unshift(newHandler) : handlers.push(newHandler)
} else if (handlers) {
events[name] = important ? [newHandler, handlers] : [handlers, newHandler]
} else {
events[name] = newHandler
}
...
}
- compile/codegen/index.js
function genData(){
if (el.events) {
data += `${genHandlers(el.events, false, state.warn)},`
}
}
- compile/codegen/events.js
function genHandler() {
...
if (!handler.modifiers) {
if (isMethodPath || isFunctionExpression) {
return handler.value
}
/* istanbul ignore if */
if (__WEEX__ && handler.params) {
return genWeexHandler(handler.params, handler.value)
}
return `function($event){${handler.value}}` // inline statement
}
...
}
经过这一步 大概会变成{ on: { click: function($events) { .... 里面是我们在html中写的代码 ... } } }
,再经过render转化为实例的events。源码中体现为:
const data = el.plain ? undefined : genData(el, state)
const children = el.inlineTemplate ? null : genChildren(el, state, true)
// _c createElement
code = `_c('${el.tag}'${
data ? `,${data}` : '' // data
}${
children ? `,${children}` : '' // children
})`
- core/instance/events.js
利用apply将第一个参数覆盖所以在v-on中我们既可以用arguments[0],又可以用$event获取第一个参数。
Vue.prototype.$emit = function() {
...
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs
const args = toArray(arguments, 1)
for (let i = 0, l = cbs.length; i < l; i++) {
try {
cbs[i].apply(vm, args)
} catch (e) {
handleError(e, vm, `event handler for "${event}"`)
}
}
}
...