2016-11-29 77 views
3

当Elm有很多DOM操作要做时,在结果显示之前会有一些滞后。我试图找出如何显示一个占位符的div,说“加载...”,而榆树正在做它的事情。在Elm渲染DOM元素时显示“加载占位符”

为了演示的滞后性,我已经修改了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 

运行示例时,点击“+”按钮将显示'。'当数字足够高时(在我的机器上大约16个),在点击''之前会有多秒的延迟。显示字符。

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

+1

我从你的示例代码看到的是,实际上浏览器渲染/布局花费最多的等待时间,而不是通过js引擎来区分虚拟DOM。您可能想要调查其他框架(或简单地通过javascript DOM api调用)如何处理它,因为它看起来不像榆树特定的。 – Tosh

回答

4

你需要使用正Html.program并返回从Increment/Decrement更新处理程序将暂停,让DOM渲染“加载”一Cmd,然后重新输入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元素的方法......