ソースを参照

properly handle inline function expressions in v-on

Evan You 9 年 前
コミット
0b78ea9696

+ 2 - 1
src/compiler/codegen/events.js

@@ -1,5 +1,6 @@
 /* @flow */
 /* @flow */
 
 
+const fnExpRE = /^\s*([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/
 const simplePathRE = /^\s*[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?']|\[".*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*\s*$/
 const simplePathRE = /^\s*[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?']|\[".*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*\s*$/
 
 
 // keyCode aliases
 // keyCode aliases
@@ -41,7 +42,7 @@ function genHandler (
   } else if (Array.isArray(handler)) {
   } else if (Array.isArray(handler)) {
     return `[${handler.map(genHandler).join(',')}]`
     return `[${handler.map(genHandler).join(',')}]`
   } else if (!handler.modifiers) {
   } else if (!handler.modifiers) {
-    return simplePathRE.test(handler.value)
+    return fnExpRE.test(handler.value) || simplePathRE.test(handler.value)
       ? handler.value
       ? handler.value
       : `function($event){${handler.value}}`
       : `function($event){${handler.value}}`
   } else {
   } else {

+ 14 - 1
test/unit/features/directives/on.spec.js

@@ -28,7 +28,7 @@ describe('Directive v-on', () => {
     expect(event.type).toBe('click')
     expect(event.type).toBe('click')
   })
   })
 
 
-  it('should bind event to a inline method', () => {
+  it('should bind event to a inline statement', () => {
     vm = new Vue({
     vm = new Vue({
       el,
       el,
       template: '<div v-on:click="foo(1,2,3,$event)"></div>',
       template: '<div v-on:click="foo(1,2,3,$event)"></div>',
@@ -46,6 +46,19 @@ describe('Directive v-on', () => {
     expect(firstArgs[3].type).toBe('click')
     expect(firstArgs[3].type).toBe('click')
   })
   })
 
 
+  it('should support inline function expression', () => {
+    const spy = jasmine.createSpy()
+    vm = new Vue({
+      el,
+      template: `<div class="test" @click="function (e) { log(e.target.className) }"></div>`,
+      methods: {
+        log: spy
+      }
+    }).$mount()
+    triggerEvent(vm.$el, 'click')
+    expect(spy).toHaveBeenCalledWith('test')
+  })
+
   it('should support shorthand', () => {
   it('should support shorthand', () => {
     vm = new Vue({
     vm = new Vue({
       el,
       el,

+ 33 - 0
test/unit/modules/compiler/codegen.spec.js

@@ -270,6 +270,39 @@ describe('codegen', () => {
     )
     )
   })
   })
 
 
+  it('generate events with inline function expression', () => {
+    // normal function
+    assertCodegen(
+      '<input @input="function () { current++ }">',
+      `with(this){return _h('input',{on:{"input":function () { current++ }}})}`
+    )
+    // arrow with no args
+    assertCodegen(
+      '<input @input="()=>current++">',
+      `with(this){return _h('input',{on:{"input":()=>current++}})}`
+    )
+    // arrow with parens, single arg
+    assertCodegen(
+      '<input @input="(e) => current++">',
+      `with(this){return _h('input',{on:{"input":(e) => current++}})}`
+    )
+    // arrow with parens, multi args
+    assertCodegen(
+      '<input @input="(a, b, c) => current++">',
+      `with(this){return _h('input',{on:{"input":(a, b, c) => current++}})}`
+    )
+    // arrow with destructuring
+    assertCodegen(
+      '<input @input="({ a, b }) => current++">',
+      `with(this){return _h('input',{on:{"input":({ a, b }) => current++}})}`
+    )
+    // arrow single arg no parens
+    assertCodegen(
+      '<input @input="e=>current++">',
+      `with(this){return _h('input',{on:{"input":e=>current++}})}`
+    )
+  })
+
   // #3893
   // #3893
   it('should not treat handler with unexpected whitespace as inline statement', () => {
   it('should not treat handler with unexpected whitespace as inline statement', () => {
     assertCodegen(
     assertCodegen(