使用 Mithril.js,为什么我的 onclick 处理程序不修改 mithril 组件?

Using Mithril.js, why does my onclick handler not modify the mithril component?

我正在制作一个测验网络应用程序。我有一个名为 "answerBox" 的 class,它目前只包含一个按钮、一个 ID 和一个布尔值。我想调用一个 "check Answer" 函数来确定我的答案是否正确。

我将 onclick 分配给匿名函数,并向该函数发送一个与 answerBox 相同的对象,但 onclick 处理程序并未更改我的 answerBox 对象。它似乎正在创建本地副本。代码在这里:

//currently just boilerplate checkAnswer function.  Eventually will involve server calls.  It is the client-side
//controller
function checkAnswer(ansBox)
{
    console.log(ansBox.IDString);
    if(ansBox.IDString == "Hello")
    {
        console.log("BEFORE: " + ansBox.IDString);
        ansBox.IDString = "Goodbye";
        console.log("AFTER: " + ansBox.IDString);
        return true;
    }
    else
    {
        ansBox.IDString = "Hello";
        return false;
    }
}

class answerBox{
    constructor(IDString){
        this.IDString = IDString;
        this.isCorrect = false;
        //to register the onclick, we need a reference to this, which we can't have unless we 
        //create it, since the button's "this" is not the same as the answerBox's "this", hence, "that".
        var that = this;
        this.checkButton = m("button",{onclick: function(){that.isCorrect = checkAnswer(that); console.log(that.isCorrect)}},"Check" + this.IDString + " " + this.isCorrect);
    }

    view()
    {
        return this.checkButton;
    }
}

我使用 Mithril 将一个 answerBox 变量安装到 root,它在网页中显示得很好。单击网页上的按钮后查看控制台时,我得到:

Hello
BEFORE: Hello
AFTER: Goodbye
true

现在,发生了两件事:

  1. 该按钮不会更改其内容。如果 answerBox 变量真的被修改了,那么它应该有一个 "Goodbye" 的 IDString,但它没有
  2. 当我再次单击该按钮时,我看到了完全相同的控制台输出,表明没有任何变化。

我做错了什么?

您编写组件的方式存在一些问题:

首先,构造函数被编写为接受单个参数,IDString - 但所有 Mithril 组件方法(包括构造函数)接收一个 vnode 对象,其中包含 attrschildren ,它们是在调用组件时通过超脚本传入的。因此,假设您将按如下方式调用您的组件:

m(answerBox, {IDString: 'answerBox1'})

...然后您将编写组件以在构造函数中接收 IDString,如下所示:

class answerBox {
  constructor(vnode){
    this.IDString = vnode.attrs.IDString;

下一个问题是 answerBox 视图在实例化后永远不会改变,因为它的内容只在构造函数中计算一次,当定义 this.checkButton 时。与其评估视图并将其分配给 属性 只是为了调用该 属性,不如直接将其写入视图函数中。然后该组件变为:

class answerBox {
  constructor(vnode){
    this.IDString = vnode.attrs.IDString;
    this.isCorrect = false;
  }

  view(){
    var that = this;

    return m("button", {
      onclick: function(){
        that.isCorrect = checkAnswer(that); 
        console.log(that.isCorrect)
      }
    },
      "Check" + this.IDString + " " + this.isCorrect
    );
  }
}

The code above should produce the intended results!