首页 > 解决方案 > Keyed Node 是否意味着与 Lazy 一起使用?

问题描述

我正在阅读 Elm Guide 中的优化。它以美国总统为例讨论了键控节点:

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 [] [ ... ]

然后给出这个解释:

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

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

标签: elm

解决方案


让我们考虑一个例子:

  • 名称: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 输入中,让它们保持键控,它将留在苹果输入,但如果它们没有键控,它现在将在香蕉输入。

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


推荐阅读