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(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(
 | 
			
		||||
  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)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -120,7 +122,6 @@ function createInvoker(
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  invoker.value = initialValue
 | 
			
		||||
  initialValue.invoker = invoker
 | 
			
		||||
  invoker.attached = getNow()
 | 
			
		||||
  return invoker
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user