使用 Mithril 在运行时创建新元素

Creating new elements at runtime using Mithril

使用 Javascript 框架 Mithril,我正在尝试添加 new 元素 after 已创建初始主体并渲染。

这是我的问题的最基本形式:

let divArray = [];
let newDivButton = m('button', { onclick: ()=> {
    divArray.push(m('div', "NEW DIV PUSHED"));
}}, "Add new div");

divArray.push(newDivButton);
divArray.push(m('div', "NEW DIV PUSHED"));

let mainDiv = {
    view: () => {
        return divArray;
    }
}

m.mount(document.body, mainDiv);

上面的代码将创建一个按钮和 一个 行文本 NEW DIV PUSHED。该按钮添加一个与第一个完全相同的新文本元素。这里的问题是即使调用了 view 函数,那些额外的元素也不会被渲染。我进入代码并清楚地看到我的 divArray 正在被填充,即使它们没有呈现。

我注意到的一件事是初始文本元素(呈现的那个)的 dom 属性 由实际 div 对象填充。我数组中所有后续文本元素的 dom 属性 设置为 undefined。我不知道如何解决这个问题,但我确信它与我的问题有关。

Mithril 在 render 生命周期中内置了优化 - it won't re-render a DOM tree if the tree is identical to the last tree。由于 divArray === divArray 始终是 true,所以节点永远不会重新渲染。

简单但不理想的解决方案是 slice 您的数组,因此您总是从 mainDiv#view 返回一个新数组,因此,Mithril 将始终重新渲染顶层数组:

let mainDiv = {
  view: () => {
    return divArray.slice();
  }
};

正确的方法是映射数据,在视图层创建vnodes,而不是在视图层静态地保存一个vnodes列表你的模块范围:

let data = ["Data Available Here"];
let mainDiv = {
  view: () => {
    return [
      m(
        'button',
        { onclick: () => data.push("Data Pushed Here") },
        "Add new div"
      );
    ].concat(
      data.map(datum => m('div', datum))
    );
  }
};