在渲染 DOM 元素时在 Elm 中显示 'loading placeholder'

Show a 'loading placeholder' in Elm while it is rendering DOM elements

当 Elm 有很多 DOM 操作要做时,在结果显示之前会有一些滞后。我正在尝试弄清楚如何在 Elm 执行操作时显示一个占位符 div,上面写着 "Loading..."。

为了演示延迟,我修改了其中一个 Elm examples 以在单击按钮时呈现越来越多的文本元素:

import Html exposing (beginnerProgram, div, button, text)
import Html.Events exposing (onClick)

main =
  beginnerProgram { model = 0, view = view, update = update }


view model =
  div []
    [ button [ onClick Decrement ] [ text "-" ]
    , div [] [ text (toString model) ]
    , button [ onClick Increment ] [ text "+" ]
    , div [] (List.repeat (2 ^ model) (text ". ")) -- this is my addition
    ]

type Msg = Increment | Decrement

update msg model =
  case msg of
    Increment ->
      model + 1

    Decrement ->
      model - 1

当运行例子时,点击'+'按钮会显示一个'.' 2 的幂中的字符。当数字足够大时(在我的机器上大约为 16),在“.”之前单击后会有多秒的延迟。显示字符。

在呈现“.”之前显示 'loading...' 元素(例如 'div' 中)的好方法是什么?元素?

您需要使用来自 Increment/Decrement 更新处理程序的常规 Html.program 和 return 一个 Cmd 将暂停让 DOM 渲染 "Loading" 然后重新输入 update:

import Html exposing (program, div, button, text)
import Html.Events exposing (onClick)
import Process
import Task

main =
  program { init = (Model 0 False, Cmd.none), view = view, update = update, subscriptions = \_ -> Sub.none }

type alias Model =
  { count: Int
  , loading: Bool
  }

view model =
  let
    dotsDisplay =
      if model.loading then
        div [] [text "Loading..."]
      else
        div [] (List.repeat (2 ^ model.count) (text ". "))
  in
    div []
      [ button [ onClick Decrement ] [ text "-" ]
      , div [] [ text (toString model.count) ]
      , button [ onClick Increment ] [ text "+" ]
      , dotsDisplay
      ]

type Msg = Increment | Decrement | FinishLoading

finishLoadingCmd =
  Task.map2 (\_ b -> b) (Process.sleep 10) (Task.succeed FinishLoading)
  |> Task.perform identity

update msg model =
  case msg of
    Increment ->
      {model | count = model.count + 1, loading = True} ! [finishLoadingCmd]

    Decrement ->
      {model | count = model.count - 1, loading = True} ! [finishLoadingCmd]

    FinishLoading ->
      {model | loading = False} ! []

它仍然会在呈现所有这些节点时锁定浏览器,因此您可能仍想寻找一种不呈现 100k+ DOM 元素的方法...