|
|
@ -1,7 +1,44 @@ |
|
|
|
/* @flow */ |
|
|
|
|
|
|
|
import { cached } from 'shared/util' |
|
|
|
import { warn } from 'core/util/index' |
|
|
|
|
|
|
|
const normalizeEvent = cached((name: string): { |
|
|
|
name: string, |
|
|
|
once: boolean, |
|
|
|
capture: boolean |
|
|
|
} => { |
|
|
|
const once = name.charAt(0) === '~' // Prefixed last, checked first
|
|
|
|
name = once ? name.slice(1) : name |
|
|
|
const capture = name.charAt(0) === '!' |
|
|
|
name = capture ? name.slice(1) : name |
|
|
|
return { |
|
|
|
name, |
|
|
|
once, |
|
|
|
capture |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
function createEventHandle (fn: Function | Array<Function>): { |
|
|
|
fn: Function | Array<Function>; |
|
|
|
invoker: Function; |
|
|
|
} { |
|
|
|
const handle = { |
|
|
|
fn, |
|
|
|
invoker: function () { |
|
|
|
const fn = handle.fn |
|
|
|
if (Array.isArray(fn)) { |
|
|
|
for (let i = 0; i < fn.length; i++) { |
|
|
|
fn[i].apply(null, arguments) |
|
|
|
} |
|
|
|
} else { |
|
|
|
fn.apply(null, arguments) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return handle |
|
|
|
} |
|
|
|
|
|
|
|
export function updateListeners ( |
|
|
|
on: Object, |
|
|
|
oldOn: Object, |
|
|
@ -9,69 +46,30 @@ export function updateListeners ( |
|
|
|
remove: Function, |
|
|
|
vm: Component |
|
|
|
) { |
|
|
|
let name, cur, old, curIsArray, oldIsArray, fn, event, capture, once |
|
|
|
let name, cur, old, event |
|
|
|
for (name in on) { |
|
|
|
cur = on[name] |
|
|
|
old = oldOn[name] |
|
|
|
curIsArray = Array.isArray(cur) |
|
|
|
oldIsArray = Array.isArray(old) |
|
|
|
event = normalizeEvent(name) |
|
|
|
if (!cur) { |
|
|
|
process.env.NODE_ENV !== 'production' && warn( |
|
|
|
`Invalid handler for event "${name}": got ` + String(cur), |
|
|
|
`Invalid handler for event "${event.name}": got ` + String(cur), |
|
|
|
vm |
|
|
|
) |
|
|
|
} else if (!old) { |
|
|
|
once = name.charAt(0) === '~' // Prefixed last, checked first
|
|
|
|
event = once ? name.slice(1) : name |
|
|
|
capture = event.charAt(0) === '!' |
|
|
|
event = capture ? event.slice(1) : event |
|
|
|
if (curIsArray) { |
|
|
|
add(event, (cur.invoker = arrInvoker(cur)), once, capture) |
|
|
|
} else { |
|
|
|
if (!cur.invoker) { |
|
|
|
fn = cur |
|
|
|
cur = on[name] = {} |
|
|
|
cur.fn = fn |
|
|
|
cur.invoker = fnInvoker(cur) |
|
|
|
} |
|
|
|
add(event, cur.invoker, once, capture) |
|
|
|
cur = on[name] = createEventHandle(cur) |
|
|
|
} |
|
|
|
add(event.name, cur.invoker, event.once, event.capture) |
|
|
|
} else if (cur !== old) { |
|
|
|
if (curIsArray || oldIsArray) { |
|
|
|
if (!curIsArray) cur = [cur] |
|
|
|
if (!oldIsArray) old = [old] |
|
|
|
old.length = cur.length |
|
|
|
for (let i = 0; i < old.length; i++) old[i] = cur[i] |
|
|
|
on[name] = old |
|
|
|
} else { |
|
|
|
old.fn = cur |
|
|
|
on[name] = old |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
for (name in oldOn) { |
|
|
|
if (!on[name]) { |
|
|
|
once = name.charAt(0) === '~' // Prefixed last, checked first
|
|
|
|
event = once ? name.slice(1) : name |
|
|
|
capture = event.charAt(0) === '!' |
|
|
|
event = capture ? event.slice(1) : event |
|
|
|
remove(event, oldOn[name].invoker, capture) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function arrInvoker (arr: Array<Function>): Function { |
|
|
|
return function (ev) { |
|
|
|
const single = arguments.length === 1 |
|
|
|
for (let i = 0; i < arr.length; i++) { |
|
|
|
single ? arr[i](ev) : arr[i].apply(null, arguments) |
|
|
|
} |
|
|
|
event = normalizeEvent(name) |
|
|
|
remove(event.name, oldOn[name].invoker, event.capture) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function fnInvoker (o: { fn: Function }): Function { |
|
|
|
return function (ev) { |
|
|
|
const single = arguments.length === 1 |
|
|
|
single ? o.fn(ev) : o.fn.apply(null, arguments) |
|
|
|
} |
|
|
|
} |
|
|
|