Javascript 为什么选择v-on:click=";方法();被视为方法声明,就像v-on:click=";方法";?

Javascript 为什么选择v-on:click=";方法();被视为方法声明,就像v-on:click=";方法";?,javascript,vue.js,Javascript,Vue.js,以这个例子为例 格里特1 欢迎2 导出默认值{ 方法:{ 方法(){ 警惕(“你好”); } } }; 尽管在v-on:click的“Greet1”中有方法声明,在“Greet2”中有方法调用,但两个按钮的工作原理完全相同(我知道在第一个示例中传递了事件) “Greet2”在组件渲染阶段不应该显示警报,而且这个按钮在单击时不应该工作,因为我没有在method()中返回函数 为什么会有这种机制以及它是如何工作的 不会立即调用该方法,因为在呈现模板之前,它会被编译成函数。在编译过程中,v-onc

以这个例子为例


格里特1
欢迎2
导出默认值{
方法:{
方法(){
警惕(“你好”);
}
}
};
尽管在
v-on:click
的“Greet1”中有方法声明,在“Greet2”中有方法调用,但两个按钮的工作原理完全相同(我知道在第一个示例中传递了事件)

“Greet2”在组件渲染阶段不应该显示警报,而且这个按钮在单击时不应该工作,因为我没有在
method()
中返回函数


为什么会有这种机制以及它是如何工作的

不会立即调用该方法,因为在呈现模板之前,它会被编译成函数。在编译过程中,
v-on
click表达式由Vue解析,并以两种不同的方式处理。本质上,在以下情况下编译模板时会发生什么

<button v-on:click="method">Greet1</button>
<button v-on:click="method()">Greet2</button>
单击处理程序设置为

function($event) { method() }
整个编译后的渲染函数被包装在一个带有(this)的
中,这样
method()
和其他以这种方式声明的内容就可以得到正确的解决

下面是一个小片段,展示了这是如何决定的

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
}

如果您通读上述链接的代码,则所讨论的函数是
genHandler
(适用于此特定版本的Vue,即2.5.13)。

免责声明:Vue是我最喜欢使用的库之一。事实上,这两个都做了相同的事情,这让人觉得Vue的模板系统在一致性方面有点缺陷。也许我希望有一个函数返回一个函数用作处理程序,例如,
@click=“createClickHandler()”
,它会调用
createClickHandler()
,而不使用从它返回的实际处理程序吗?@kingdaro我的期望是Vue会调用createClickHandler,而不是从它返回的函数。但我会测试并检查它!我要提到的一点是,使用模板不是强制性的;您始终可以编写自己的渲染函数。真的不难。@kingdaro这是答案。正如所料,
createClickHandler
将作为函数调用。正如@everettss所建议的,有一种简单(尽管可能不是直观的)的方法可以解决这个问题。我这样想,我想这很好,因为我提出的方案并不太常见。尽管如此,我还是认为vue将来最好始终使用
method()
表单,以减少歧义。我听说很快就会有更新(可能是在接下来的几个月吧?),我想知道这是否是他们所想的about@Everettss我只能猜测原因。我想这主要是为了灵活性。对于内联处理程序,在某些情况下,您可能希望向处理程序传递多个参数。或者,您可能希望使用上述讨论中描述的函数工厂;在这些情况下,您需要内联处理程序语法。然而,为了便于使用,当您只想让处理程序调用您的一个方法时,只需指定该方法就好了。在我自己的代码中,唯一一次真正使用内联语法
method()
是在我打算传递参数时。
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
}