【问题标题】:Is Keyed Node meant to be used with Lazy?Keyed Node 是否意味着与 Lazy 一起使用?
【发布时间】:2021-09-10 10:16:17
【问题描述】:

我正在阅读 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 [] [ ... ]

那就解释一下吧:

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

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

【问题讨论】:

  • 我的理解是它们在不同的层次上工作。 lazy 使用记忆来跳过虚拟 DOM 树的部分计算。键控节点通过将 DOM 节点与其在虚拟 DOM 树中的对应节点进行匹配来减少 DOM 操作的数量。
  • 这也是我的理解。但在我看来,如果不同时使用lazy,键控节点的有效性将大大降低。我只是想确认一下怀疑。
  • 无论你是否使用lazy,都应该产生完全相同的虚拟DOM树。使用lazy 只会返回一个先前计算的虚拟DOM 片段,而不是重新计算它。我根本看不出它们会如何相互影响。
  • 好的。如果我不使用lazy,则列表中的每个条目都将被重新计算,而不管键匹配如何。不是吗?
  • 是的,这是我的理解。这只是记忆化,这意味着结果会根据其输入进行缓存,并且仅根据其输入进行缓存。

标签: elm


【解决方案1】:

让我们考虑一个例子:

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

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

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

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

  • 名称Apple香蕉价格:$3.22,pic ??
  • 名称香蕉橙色价格:$22.8 em>,图片??
  • 名称橙色Apple价格:$2.83.2 em>,图片??

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

keyed 版本会理解订单已更改,并将为苹果节点发出一个 removeChildappendChild

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

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

【讨论】:

  • “你是对的,没有懒惰,差异仍然会发生”我不认为lazy 与差异有任何关系。它记忆了部分虚拟 DOM,但仍然需要对整个虚拟 DOM 进行区分。
猜你喜欢
  • 1970-01-01
  • 2015-09-22
  • 1970-01-01
  • 2010-12-10
  • 2014-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-07
相关资源
最近更新 更多