增量按钮分别在Mithril组件构成

时间:2017-11-21 06:39:03

标签: javascript closures mithril.js factory-method

我对Mithril.js中组件的组成方式感到困惑。在下面的示例中,我创建了一个按钮组件,用于保持按钮单击次数的私密计数。如果我将两个这样的组件(下面的按钮1和2)分别安装到两个安装点(下面的“m1”和“m2”),我可以正确地初始化和增加按钮单击的计数

但是,如果我在一个较大的组件中包含两个按钮组件(下面的按钮3和4)并将此包装组件安装到安装点(“m3”),则按钮单击不会增加。这里有什么问题以及如何解决它?

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <script src="https://unpkg.com/mithril/mithril.js"></script>
  </head>

  <body>
    <h1>This works:</h1>
    <div id="m1"></div>
    <div id="m2"></div>
    <h1>This doesn't work:</h1>
    <div id="m3"></div>

    <script>
      // The factory method to generate a button component
      function createButton(options) {
        let {title, count} = options;
        return {view: () => [
          m("span", title),
          m("button", {onclick: function() {count++}}, count + " clicks"),
        ]};
      };      

      (function() {
        // this works
        m.mount(document.getElementById("m1"), createButton({title: "button 1 ", count: 0}));
        m.mount(document.getElementById("m2"), createButton({title: "button 2 ", count: 10}));

        // this doesn't work
        m.mount(document.getElementById("m3"), {view: () => [
          m("div", [m(createButton({title: "button 3 ", count:  0}))]),
          m("div", [m(createButton({title: "button 4 ", count: 10}))]),
        ]});
      })();
    </script>
  </body>
</html>

2 个答案:

答案 0 :(得分:2)

第二个版本是在每次重绘时使用全新参数创建一个全新的组件,因此每个事件都会删除count值。

如果您改为使用秘银closure components,那么它就可以满足您的需求。

// Button closure component
function createButton(vnode) {
  let {title, count} = vnode.attrs;

  return {
    view: () => [
      m("span", title),
      m("button", {onclick: function() {count++}}, count + " clicks"),
    ]
  };
};      

(function() {
  m.mount(document.getElementById("m3"), {view: () => [
    m("div", [m(createButton, {title: "button 3 ", count:  0})]),
    m("div", [m(createButton, {title: "button 4 ", count: 10})]),
  ]});
})();

https://jsbin.com/mazujij/2/edit?js,output

答案 1 :(得分:0)

我发现如果按钮组件3和4预先创建 (而不是在包装器组件的view()体内即时运行),按钮将正常运行。但是,我仍然不知道为什么按钮1和2可以在运行中定义,但按钮3和4不能。

    <script>
      (function() {
        // this works
        m.mount(document.getElementById("m1"), createButton({title: "button 1 ", count: 0}));
        m.mount(document.getElementById("m2"), createButton({title: "button 2 ", count: 10}));

        // now this also works
        let b3 = createButton({title: "button 3 ", count:  0});  // created beforehand
        let b4 = createButton({title: "button 4 ", count: 10});  // created beforehand
        m.mount(document.getElementById("m3"), {view: () => [
          m("div", [m(b3)]),
          m("div", [m(b4)]),
        ]});
      })();
    </script>