当我从头开始删除元素时,为什么 m.render() 不更新视图?

Why does m.render() not update view when i remove elements from begining?

在这里,我正在尝试更新文档以包含一些元素,并且我正在逐步删除。我尝试了两种方法,一种不涉及创建 m-objects,另一种是在每个 m.render() 上创建新的 m-objects。我在我的程序中使用了第一种方法,但它没有用,所以我决定测试 Mithril 并发现了这种行为。

这不起作用:

e1 = m('i', 'e1');
e2 = m('i', 'e2');
e3 = m('i', 'e3');
m.render(document.body, m('b', [e1, e2, e3]));
// "e1e2e3" appears
m.render(document.body, m('b', [e2, e3]));
// "e2e3" appears
m.render(document.body, m('b', [e3]));
// "e2e3" appears
m.render(document.body, m('b', []));
// "e2e3" appears

有趣的是,如果我从末尾删除项目,它会起作用:

e1 = m('i', 'e1');
e2 = m('i', 'e2');
e3 = m('i', 'e3');
m.render(document.body, m('b', [e1, e2, e3]));
// "e1e2e3" appears
m.render(document.body, m('b', [e1, e2]));
// "e1e2" appears
m.render(document.body, m('b', [e1]));
// "e1" appears
m.render(document.body, m('b', []));
// "" appears

而且,此方法始终有效(双向):

m.render(document.body, m('b', [m('i', 'e1'), m('i', 'e2'), m('i', 'e3')]));
// "e1e2e3" appears
m.render(document.body, m('b', [m('i', 'e2'), m('i', 'e3')]));
// "e2e3" appears
m.render(document.body, m('b', [m('i', 'e3')]));
// "e3" appears
m.render(document.body, m('b', []));
// "" appears

我想我可以在我的程序中使用最后一种方法,但我想知道为什么原来的方法不起作用。

使用键:https://mithril.js.org/keys.html

当您处理可能会更改的数据列表(重新排序或 add/remove 项)时,最好为与数据相关的每个 component/element 设置一个 key它呈现。

我不太确定 Mithril 在这里做了什么,但如果没有密钥,它就无法正确识别每次都删除了哪些子项。 (从列表末尾删除时更有效。)

然而,使用正确的键,它总是有效的:

var children = [
    m('i', {key: 'e1'}, 'e1'),
    m('i', {key: 'e2'}, 'e2'),
    m('i', {key: 'e3'}, 'e3')
];

function show() {
    m.render(document.body, m('b', {onclick: removeFirst}, children));
}

function removeFirst() {
    children = children.slice(1);
    console.log('children', children);
    show();
}

show();
<body>
    <script src="https://unpkg.com/mithril/mithril.js"></script>
    <script src="index.js"></script>
</body>