我正在阅读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 [] [ ... ]
然后给出如下解释:
现在虚拟DOM实现可以识别何时使用列表。它首先按键匹配所有总统。然后对它们求微分。我们对每个条目都使用了lazy,所以我们可以跳过所有的工作。好了!然后,它计算出如何对DOM节点进行洗牌,以按照您想要的顺序显示内容。因此,键控版本最终做的工作要少得多。
我的困惑是这样的:如果我不使用lazy
内键节点,虚拟DOM仍然必须区分列表的每个条目,即使它可以匹配某些键。关键节点的有用性似乎真的取决于里面的lazy
。我的理解对吗?
让我们考虑一个例子:
名字- : Apple,价格: $3.2,pic:🍏 <
- 名称/strong>:香蕉,价格: $2,pic:🍌 <
- 名称/strong>: Orange,price: $2.8,pic:🍊
现在假设用户按价格排序:
名字- :香蕉,价格: $2,pic:🍌 <
- 名称/strong>: Orange,price: $2.8,pic:🍊 <
- 名称/strong>: Apple,价格: $3.2,pic:🍏
没有关键节点,区别将看起来像这样:名字
- 苹果:
香蕉,价格: $3.22,pic:🍏del>🍌< - 名称/strong>香蕉:
橙色,价格: $22.8,pic:🍌🍊 < - 名称/strong>橙色:
苹果,价格: $2.83.2,pic:🍊del>🍏
它将在这个例子中发出9个replaceElement
操作和9个createTextElement
操作(例如,确切的语义可能会略有不同,但我认为这一点是成立的)。
键控版本将理解订单更改,并将为apple节点发出单个removeChild
和appendChild
。
因此,所有的性能节省都在DOM端。这不仅仅是为了性能,如果这些列表有输入元素,保持它们的键值如果你的光标在苹果输入,它会留在苹果输入,但如果它们没有键值,它现在会在香蕉输入。
你是正确的,如果没有lazy,区别仍然会发生,但区别通常是便宜的部分,更昂贵的部分实际上是修补DOM,这是keyed帮助防止的。