Keyed Node 是否适合与 Lazy 一起使用?

Nic*_*Lee 1 elm

我正在《Elm 指南》中阅读有关优化的内容。它讨论了键控节点,以美国总统为例:

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 [] [ ... ]
Run Code Online (Sandbox Code Playgroud)

然后给出这个作为解释:

现在,虚拟 DOM 实现可以识别何时重新排列列表。它首先通过密钥匹配所有总统。然后它区分这些。我们对每个条目都使用了惰性,因此我们可以跳过所有这些工作。好的!然后它会弄清楚如何打乱 DOM 节点以按照您想要的顺序显示内容。所以键控版本最终要做的工作要少得多。

我的困惑是:如果我不在lazy键控节点内部使用,虚拟 DOM 仍然必须比较列表中的每个条目,即使它可以匹配某些键。看来键控节点的有用性确实取决于lazy内部。我的理解正确吗?

Jak*_*mpl 5

让我们考虑一个例子:

  • 名称:Apple,价格:$3.2,图片
  • 名称:香蕉,价格:$2,图片
  • 名称:橙子,价格:$2.8,图片

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

  • 名称:香蕉,价格:$2,图片
  • 名称:橙子,价格:$2.8,图片
  • 名称:Apple,价格:$3.2,图片

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

  • 姓名苹果香蕉,价格: $3.22、图片
  • 姓名香蕉橙子,价格: $22.8如图
  • 姓名橙子苹果价格:$2.83.2如图

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

键控版本将了解订单已更改,并将为苹果节点发出单个removeChild和。appendChild

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

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