Everettss
Everettss

Reputation: 16039

Why v-on:click="method()" is treat as a method declaration like the v-on:click="method"?

Consider this example https://codesandbox.io/s/1yvp4zz5x7?module=%2Fsrc%2FApp.vue

<template>
  <div>
    <button v-on:click="method">Greet1</button>
    <button v-on:click="method()">Greet2</button>
  </div>  
</template>

<script>
  export default {
    methods: {
      method() {
        alert('Hello');
      }
    }
  };
</script>

Both buttons will work exactly the same (I'm aware of passing event in the first example) despite the fact that in v-on:click in "Greet1" there is method declaration and in "Greet2" there is method invokation.

Shouldn't "Greet2" display alert during component rendering phase and this button shouldn't work on clicking since I didn't return function in method()?

Why there is this mechanism here and how it works?

Upvotes: 3

Views: 86

Answers (1)

Bert
Bert

Reputation: 82459

The method is not called immediately, because before the template is ever rendered, it is compiled into a function. During the compilation process, the v-on click expression is parsed by Vue and handled in two separate ways. Essentially, what happens when the template is compiled in the case of

<button v-on:click="method">Greet1</button>

is that the click handler is set directly to method. In the case of

<button v-on:click="method()">Greet2</button>

the click handler is set to

function($event) { method() }

The entire compiled render function is wrapped in a with(this) so that method() and other things that are declared that way are resolved properly.

Here is a little snippet from the generated code that shows how this is decided.

var fnExpRE = /^\s*([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/;
var simplePathRE = /^\s*[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['.*?']|\[".*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*\s*$/;

...many lines omitted...

var isMethodPath = simplePathRE.test(handler.value);
var isFunctionExpression = fnExpRE.test(handler.value);

if (!handler.modifiers) {
  if (isMethodPath || isFunctionExpression) {
    return handler.value
  }

  return ("function($event){" + (handler.value) + "}") // inline statement
}

If you read through the code of the above link, the function in question is genHandler (for this particular version of Vue, which is 2.5.13).

Upvotes: 3

Related Questions