Keyed Node 是否要与 Lazy 一起使用?

Is Keyed Node meant to be used with Lazy?

我正在阅读 Elm 指南中有关优化的内容。它讲的是keyed nodes,以美国总统为例:

import Html exposing (..)
import Html.Keyed as Keyed
import Html.Lazy exposing (lazy)

viewPresidents : List President -> Html msg
viewPresidents presidents =
  Keyed.node "ul" [] (List.map viewKeyedPresident presidents)

viewKeyedPresident : President -> (String, Html msg)
viewKeyedPresident president =
  ( president.name, lazy viewPresident president )

viewPresident : President -> Html msg
viewPresident president =
  li [] [ ... ]

那就解释一下:

Now the Virtual DOM implementation can recognize when the list is resorted. It first matches all the presidents up by key. Then it diffs those. We used lazy for each entry, so we can skip all that work. Nice! It then figures out how to shuffle the DOM nodes to show things in the order you want. So the keyed version does a lot less work in the end.

我的困惑是:如果我不在键控节点中使用lazy,虚拟DOM仍然必须区分每个条目列表,即使它可以匹配某些键。看起来 keyed nodes 的用处真的取决于里面的 lazy 。我的理解正确吗?

让我们考虑一个例子:

  • 名称:苹果,价格:3.2美元,图片
  • 名称:香蕉,价格:2美元,图片
  • 名称:橙色,价格:2.8美元,图片

现在假设用户按价格排序:

  • 名称:香蕉,价格:2美元,图片
  • 名称:橙色,价格:2.8美元,图片
  • 名称:苹果,价格:3.2美元,图片

没有键控节点,差异将如下所示:

  • 名称: 苹果香蕉, 价格: $3.22, pic:
  • 名称: 香蕉橙色, 价格: $22.8, pic:
  • 名称:橙色苹果,价格: $2.83.2, pic:

在这个例子中将发布 9 replaceElement 操作和 9 createTextElement 操作(例如,确切的语义可能略有不同,但我认为这一点是成立的)。

键控版本会理解顺序发生了变化,并会为苹果节点发出单个 removeChildappendChild

因此,所有性能节省都在 DOM 方面。现在这不仅仅是为了性能,如果这些列表有输入元素,如果您将光标放在 Apple 输入中,将它们保持键控状态,它将保留在苹果输入中,但如果它们没有键控,它现在将位于香蕉输入。

你是对的,没有 lazy 差异仍然会发生,但差异通常是便宜的部分,更昂贵的部分实际上是修补 DOM,这是 keyed 帮助防止的。