]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-dom): support native onxxx handlers
authorEvan You <yyx990803@gmail.com>
Tue, 7 Apr 2020 15:34:54 +0000 (11:34 -0400)
committerEvan You <yyx990803@gmail.com>
Tue, 7 Apr 2020 15:34:54 +0000 (11:34 -0400)
close #927

packages/runtime-dom/__tests__/modules/events.spec.ts
packages/runtime-dom/src/modules/events.ts
packages/runtime-dom/src/patchProp.ts

index 2021a1547c57844a24c3ff3360b227a77e3346f4..cb053482b56ec009b4b62f5e700f7de1ae0e581f 100644 (file)
@@ -7,7 +7,7 @@ describe(`events`, () => {
     const el = document.createElement('div')
     const event = new Event('click')
     const fn = jest.fn()
-    patchEvent(el, 'click', null, fn, null)
+    patchEvent(el, 'onClick', null, fn, null)
     el.dispatchEvent(event)
     await timeout()
     el.dispatchEvent(event)
@@ -22,9 +22,9 @@ describe(`events`, () => {
     const event = new Event('click')
     const prevFn = jest.fn()
     const nextFn = jest.fn()
-    patchEvent(el, 'click', null, prevFn, null)
+    patchEvent(el, 'onClick', null, prevFn, null)
     el.dispatchEvent(event)
-    patchEvent(el, 'click', prevFn, nextFn, null)
+    patchEvent(el, 'onClick', prevFn, nextFn, null)
     await timeout()
     el.dispatchEvent(event)
     await timeout()
@@ -39,7 +39,7 @@ describe(`events`, () => {
     const event = new Event('click')
     const fn1 = jest.fn()
     const fn2 = jest.fn()
-    patchEvent(el, 'click', null, [fn1, fn2], null)
+    patchEvent(el, 'onClick', null, [fn1, fn2], null)
     el.dispatchEvent(event)
     await timeout()
     expect(fn1).toHaveBeenCalledTimes(1)
@@ -50,8 +50,8 @@ describe(`events`, () => {
     const el = document.createElement('div')
     const event = new Event('click')
     const fn = jest.fn()
-    patchEvent(el, 'click', null, fn, null)
-    patchEvent(el, 'click', fn, null, null)
+    patchEvent(el, 'onClick', null, fn, null)
+    patchEvent(el, 'onClick', fn, null, null)
     el.dispatchEvent(event)
     await timeout()
     expect(fn).not.toHaveBeenCalled()
@@ -67,7 +67,7 @@ describe(`events`, () => {
         once: true
       }
     }
-    patchEvent(el, 'click', null, nextValue, null)
+    patchEvent(el, 'onClick', null, nextValue, null)
     el.dispatchEvent(event)
     await timeout()
     el.dispatchEvent(event)
@@ -86,8 +86,8 @@ describe(`events`, () => {
         once: true
       }
     }
-    patchEvent(el, 'click', null, prevFn, null)
-    patchEvent(el, 'click', prevFn, nextValue, null)
+    patchEvent(el, 'onClick', null, prevFn, null)
+    patchEvent(el, 'onClick', prevFn, nextValue, null)
     el.dispatchEvent(event)
     await timeout()
     el.dispatchEvent(event)
@@ -106,12 +106,30 @@ describe(`events`, () => {
         once: true
       }
     }
-    patchEvent(el, 'click', null, nextValue, null)
-    patchEvent(el, 'click', nextValue, null, null)
+    patchEvent(el, 'onClick', null, nextValue, null)
+    patchEvent(el, 'onClick', nextValue, null, null)
     el.dispatchEvent(event)
     await timeout()
     el.dispatchEvent(event)
     await timeout()
     expect(fn).not.toHaveBeenCalled()
   })
+
+  it('should assign native onclick attribute', async () => {
+    const el = document.createElement('div')
+    const event = new Event('click')
+    const fn = ((window as any)._nativeClickSpy = jest.fn())
+
+    patchEvent(el, 'onclick', null, '_nativeClickSpy()' as any)
+    el.dispatchEvent(event)
+    await timeout()
+    expect(fn).toHaveBeenCalledTimes(1)
+
+    const fn2 = jest.fn()
+    patchEvent(el, 'onclick', null, fn2)
+    el.dispatchEvent(event)
+    await timeout()
+    expect(fn).toHaveBeenCalledTimes(1)
+    expect(fn2).toHaveBeenCalledTimes(1)
+  })
 })
index 11b060a879d2e57870d3b10f9cc14db954a66d5f..0ac69479e526e3a775808894d5db6f0379b504cd 100644 (file)
@@ -1,4 +1,4 @@
-import { EMPTY_OBJ } from '@vue/shared'
+import { EMPTY_OBJ, isString } from '@vue/shared'
 import {
   ComponentInternalInstance,
   callWithAsyncErrorHandling
@@ -66,11 +66,22 @@ export function removeEventListener(
 
 export function patchEvent(
   el: Element,
-  name: string,
+  rawName: string,
   prevValue: EventValueWithOptions | EventValue | null,
   nextValue: EventValueWithOptions | EventValue | null,
   instance: ComponentInternalInstance | null = null
 ) {
+  // support native onxxx handlers
+  if (rawName in el) {
+    if (isString(nextValue)) {
+      el.setAttribute(rawName, nextValue)
+    } else {
+      ;(el as any)[rawName] = nextValue
+    }
+    return
+  }
+
+  const name = rawName.slice(2).toLowerCase()
   const prevOptions = prevValue && 'options' in prevValue && prevValue.options
   const nextOptions = nextValue && 'options' in nextValue && nextValue.options
   const invoker = prevValue && prevValue.invoker
index a0e9e04227d955a428da073d946a024030b283fb..013dfbf00f463c4584bf3425358f1c1f7c7ac39f 100644 (file)
@@ -29,13 +29,7 @@ export const patchProp: RendererOptions<Node, Element>['patchProp'] = (
       if (isOn(key)) {
         // ignore v-model listeners
         if (key.indexOf('onUpdate:') < 0) {
-          patchEvent(
-            el,
-            key.slice(2).toLowerCase(),
-            prevValue,
-            nextValue,
-            parentComponent
-          )
+          patchEvent(el, key, prevValue, nextValue, parentComponent)
         }
       } else if (!isSVG && key in el) {
         patchDOMProp(