使用 Mithril.js,如何将异步函数给出的选项添加到先前添加的 select 元素

Using Mithril.js, how can I add options given by an async function, to a previously added select element

我正在尝试向先前创建的 Vnode(select 元素)添加选项。 在选项可用之前返回元素,因为它们来自异步函数。

尽管我尝试在回调时设置子元素,但这并没有改变呈现的元素。 select 元素中不显示选项。

我的代码如下:

const getSelect = function (field: FieldDef, key: string) {
  const elem = m('div', { class: 'field' }, [
    m('label', { class: 'label' }, field.label ? field.label : field.name),
    m(
      'div',
      {
        class: field.controlClass
          ? 'select ' + field.controlClass
          : 'select is-small',
        onchange: (val: number | string) => {
          console.log(val);
        },
      },
      [
        m(
          'select',
          {
            class: field.class ? field.class : '',
            name: field.name ? field.name : key,
            id: key,
            value: field.value,
          },
          [],
        ),
      ],
    ),
  ]);

  if (field.options) {
    void field.options().then(function (items) {
      elem.children = [];

      elem.children.push(
        items.map((i) => {
          return m('option', { value: i.value }, i.text);
        }),
      );

      console.log('the options are:');
      console.log(elem.children);
    });
  }

  return elem;
};

您的代码混合使用 expressions and statements 来描述视图:自 2013 年以来,Mithril 和大多数 Javascript 视图库都试图将其分开。解决方案是通过从模型中插入值来专门将视图描述为表达式,必要时可以通过视图外部的语句更改这些值。

您的代码示例无法运行的原因是无法操纵 vnode:相反,必须生成包含适当数据的新 vnode。

解决办法是:

  1. 动态数据模型
  2. 为任何动态值引用模型的视图表达式
  3. 可以更改模型值并指示视图重新计算的控制代码

在下面的代码中,我用一个 select 元素来近似你的问题案例,其选项稍后会改变。为了简化此示例,异步更改来自用户与视图的交互——而不是代码中的承诺——但原则保持不变:接收新选项的代码,无论它是什么,都会更改模型并指示m.redraw 的视图;当视图重绘时,它从模型中插入它的持久引用,接收一个新值,并将更改持久化到 DOM.

// 1. A dynamic data model
const model = {
  options: [],
}

m.mount(document.body, {
  // 2. A view expression that references the model for any dynamic values
  view: () => [ 
    m('select',
      model.options.map(value => 
        m('option', value),
      ),
    ),
    
    m('hr'),
    
    m('button', {
      onclick : populate,
    },
      'Populate'
    ),
    
    
    m('button', {
      onclick : reset,
    },
      'Reset'
    ),
  ],
})

// 3. Control code which can change the model values and instruct the view to recompute
function populate(){
  model.options = [1, 2, 3]

  m.redraw()
}

function reset(){
  model.options = []

  m.redraw()
}
<script src="https://unpkg.com/mithril@2.0.4/mithril.min.js"></script>