JS + Vue3:模态对话框:调用函数返回的参数化函数

JS + Vue3: Modal dialog: call parameterized function returned by function

首先,我不确定这是一个 Vue 问题还是只是一个 JavaScript 相关问题。 我写了一些代码终于可以工作了,但我不知道为什么。或许你能赐教。

我创建了一个“对话框 window”组件。这是一个简单的(模态)对话框,它将函数作为参数。如果用户单击“确定”,则调用该函数——例如“您真的要删除该文件吗?”取消或确定。

我传递给组件的函数有时本身就有一个参数。 所以我想将已经 参数化的函数 作为参数传递给我的组件。 我通过将函数包装在箭头函数中来实现这一点,箭头函数 returns 然后可以调用参数化函数。

这个概念在纯JS中的思路是这样的:

//the function to be finally executed
function say(message) {
  document.getElementById("output").innerHTML = message;
}

//the parameterized function inside of an arrow function (as a variable)
const sayhelloworld = () => say("hello world");

//finally I call the arrow function which 
//returns the parameterized function and calls this one as well
function start() {
  sayhelloworld()(); //this is the core of my question: the double brackets!
}

所以我需要双括号。第一个()returns里面的函数,第二个()调用它。 它确实像这样工作: https://codepen.io/keztur/pen/powaLJN

现在让我们转向vue:

我用事件总线打开我的对话框组件(对此感到抱歉)并传递一个包含函数参数的参数对象。 (我使用 Vue 3 - 所以在我的 EventBus 对象后面实际上是 'mitt' 库:https://github.com/developit/mitt

//component calling the dialog and passing the function parameter 
//(as a part of a parameter object)
EventBus.emit("OpenDialog", {
    header: "Delete file",
    body: "Do you really want to delete that file?",
    function: () => this.Delete(file_id)
});

模态组件:

  data() {
    return {
      show: false,
      ModalProps: {
        header: "",
        body: "",
        function: ""
      }
    };
  },

//inside of the modal component this function is called 
//if the user clicks any of the two buttons (cancel or OK)
  methods: {
    clicked(button) {
      if (button === 'ok' && typeof this.ModalProps.function === 'function') {
        this.ModalProps.function(); //why does this work ...
       //this.ModalProps.function()(); //...but not this?
 //the second line does call the function but also throws an error afterwards
      }
      this.show = false; //modal is closed
    }
  },
... etc.

所以起初我在上面的 JS 示例中使用了双括号。该函数被正确调用,但第二个“执行”backets 显然抛出了一个错误:

[Vue warn]: Unhandled error during execution of native event handler 
  at <Modal> 
  at <App>

但是由于我删除了第二个括号,所以一切正常。

所以我的问题是:为什么在 Vue 中我的箭头函数中的函数会立即被调用而不只是通过引用返回?

您的第一个示例不起作用。它应该只是 sayhelloworld();。在 运行 时打开(浏览器或代码笔)控制台。它会说:

TypeError: sayhelloworld() is not a function 

它只是看起来有效,因为错误之后没有更多的事情要做。例如,尝试在 sayhelloworld()(); 之后添加 alert("Done"),您会注意到永远不会显示警报。

Vue 的区别在于 Vue 捕获并显示错误。

sayhelloworld(以及您的 Vue 示例中的 this.ModalProps.function)只是普通(引用)函数,没有 return 任何内容。

之间没有(*)区别
const sayhelloworld = () => say("hello world");

const sayhelloworld = function() {
  say("hello world");
}

function sayhelloworld() {
  say("hello world");
}

如果函数 return 本身就是一个函数,您将使用 ()(),例如:

function sayhelloworld() {
  const innerFunction = function () {
    say("hello world");
  }
  return innerFunction;
}

function sayhelloworld() {
  return () => say("hello world");
}

甚至

const sayhelloworld = () => () => say("hello world");

这些示例再次做同样的事情(*)。


(*) 它们并不完全相同,主要是关于 hoisting 以及如何在函数内部处理 this,但这与此处无关。