expect(fn1).toHaveBeenCalledTimes(1)
expect(fn2).toHaveBeenCalledTimes(0)
})
+
+ // #1747
+ it('should handle same computed handler function being bound on multiple targets', async () => {
+ const el1 = document.createElement('div')
+ const el2 = document.createElement('div')
+
+ const event = new Event('click')
+ const prevFn = jest.fn()
+ const nextFn = jest.fn()
+
+ patchProp(el1, 'onClick', null, prevFn)
+ patchProp(el2, 'onClick', null, prevFn)
+
+ el1.dispatchEvent(event)
+ el2.dispatchEvent(event)
+ await timeout()
+ expect(prevFn).toHaveBeenCalledTimes(2)
+ expect(nextFn).toHaveBeenCalledTimes(0)
+
+ patchProp(el1, 'onClick', prevFn, nextFn)
+ patchProp(el2, 'onClick', prevFn, nextFn)
+
+ el1.dispatchEvent(event)
+ el2.dispatchEvent(event)
+ await timeout()
+ expect(prevFn).toHaveBeenCalledTimes(2)
+ expect(nextFn).toHaveBeenCalledTimes(2)
+
+ el1.dispatchEvent(event)
+ el2.dispatchEvent(event)
+ await timeout()
+ expect(prevFn).toHaveBeenCalledTimes(2)
+ expect(nextFn).toHaveBeenCalledTimes(4)
+ })
})
}
export function patchEvent(
- el: Element,
+ el: Element & { _vei?: Record<string, Invoker | undefined> },
rawName: string,
prevValue: EventValue | null,
nextValue: EventValue | null,
instance: ComponentInternalInstance | null = null
) {
- const invoker = prevValue && prevValue.invoker
- if (nextValue && invoker) {
+ // vei = vue event invokers
+ const invokers = el._vei || (el._vei = {})
+ const existingInvoker = invokers[rawName]
+ if (nextValue && existingInvoker) {
// patch
;(prevValue as EventValue).invoker = null
- invoker.value = nextValue
- nextValue.invoker = invoker
+ existingInvoker.value = nextValue
} else {
const [name, options] = parseName(rawName)
if (nextValue) {
- addEventListener(el, name, createInvoker(nextValue, instance), options)
- } else if (invoker) {
+ const invoker = (invokers[rawName] = createInvoker(nextValue, instance))
+ addEventListener(el, name, invoker, options)
+ } else if (existingInvoker) {
// remove
- removeEventListener(el, name, invoker, options)
+ removeEventListener(el, name, existingInvoker, options)
}
}
}
}
}
invoker.value = initialValue
- initialValue.invoker = invoker
invoker.attached = getNow()
return invoker
}