fix(runtime-dom): fix v-on same computed handler on multiple elements
fix #1747
This commit is contained in:
parent
b2a91429ed
commit
1c967fc44b
@ -119,4 +119,38 @@ describe(`runtime-dom: events patching`, () => {
|
|||||||
expect(fn1).toHaveBeenCalledTimes(1)
|
expect(fn1).toHaveBeenCalledTimes(1)
|
||||||
expect(fn2).toHaveBeenCalledTimes(0)
|
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)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -59,25 +59,27 @@ export function removeEventListener(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function patchEvent(
|
export function patchEvent(
|
||||||
el: Element,
|
el: Element & { _vei?: Record<string, Invoker | undefined> },
|
||||||
rawName: string,
|
rawName: string,
|
||||||
prevValue: EventValue | null,
|
prevValue: EventValue | null,
|
||||||
nextValue: EventValue | null,
|
nextValue: EventValue | null,
|
||||||
instance: ComponentInternalInstance | null = null
|
instance: ComponentInternalInstance | null = null
|
||||||
) {
|
) {
|
||||||
const invoker = prevValue && prevValue.invoker
|
// vei = vue event invokers
|
||||||
if (nextValue && invoker) {
|
const invokers = el._vei || (el._vei = {})
|
||||||
|
const existingInvoker = invokers[rawName]
|
||||||
|
if (nextValue && existingInvoker) {
|
||||||
// patch
|
// patch
|
||||||
;(prevValue as EventValue).invoker = null
|
;(prevValue as EventValue).invoker = null
|
||||||
invoker.value = nextValue
|
existingInvoker.value = nextValue
|
||||||
nextValue.invoker = invoker
|
|
||||||
} else {
|
} else {
|
||||||
const [name, options] = parseName(rawName)
|
const [name, options] = parseName(rawName)
|
||||||
if (nextValue) {
|
if (nextValue) {
|
||||||
addEventListener(el, name, createInvoker(nextValue, instance), options)
|
const invoker = (invokers[rawName] = createInvoker(nextValue, instance))
|
||||||
} else if (invoker) {
|
addEventListener(el, name, invoker, options)
|
||||||
|
} else if (existingInvoker) {
|
||||||
// remove
|
// remove
|
||||||
removeEventListener(el, name, invoker, options)
|
removeEventListener(el, name, existingInvoker, options)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,7 +122,6 @@ function createInvoker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
invoker.value = initialValue
|
invoker.value = initialValue
|
||||||
initialValue.invoker = invoker
|
|
||||||
invoker.attached = getNow()
|
invoker.attached = getNow()
|
||||||
return invoker
|
return invoker
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user