【发布时间】:2020-08-14 22:04:00
【问题描述】:
我想使用 Elm 制作一个包含一些视频元素的 Web 应用程序,其动态布局可以根据浏览器的宽度和高度进行更改。当我尝试这样做时,很明显 Elm 正在为视频生成新元素,但这不起作用,因为视频元素具有需要保留的状态。
为了简单起见,我用计数器而不是视频来演示这个问题。我试图用Html.lazy 和Keyed.node 解决这个问题,但它仍然存在。
这里的代码也可以从https://github.com/ijt/elm-dom-elt-reuse克隆过来。
src/Main.elm:
port module Main exposing (..)
import Browser
import Html exposing (..)
import Html.Attributes as Attribute exposing (id, style)
import Html.Events exposing (onClick)
main =
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
type alias Model =
{ layout : Layout }
type Layout
= Row
| Column
init : () -> ( Model, Cmd Msg )
init _ =
( { layout = Row }, startCounters () )
type Msg
= ToggleLayout
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ToggleLayout ->
let
l2 =
case model.layout of
Row ->
Column
Column ->
Row
in
( { model | layout = l2 }, Cmd.none )
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
view : Model -> Html Msg
view model =
div []
[ button [ onClick ToggleLayout ] [ text "Toggle Layout" ]
, counters model
]
counters : Model -> Html Msg
counters model =
case model.layout of
Column ->
div []
[ div [] [ counter1 ]
, div [] [ counter2 ]
]
Row ->
div [] [ counter1, spacer, counter2 ]
spacer : Html Msg
spacer =
text " "
counter1 : Html Msg
counter1 =
span [ id "counter1" ]
[ text "0" ]
counter2 : Html Msg
counter2 =
span [ id "counter2" ]
[ text "0" ]
port startCounters : () -> Cmd msg
static/index.html:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Main</title>
<style>body { padding: 0; margin: 0; }</style>
</head>
<body>
<pre id="elm"></pre>
<script src="Main.js"></script>
<script>
window.app = Elm.Main.init( { node: document.getElementById("elm") } );
window.app.ports.startCounters.subscribe(function() {
let c1 = document.getElementById("counter1");
let c2 = document.getElementById("counter2");
function increment(e) {
let n = parseInt(e.innerText);
e.innerText = n + 1;
}
requestAnimationFrame(function() {
setInterval(function() {
increment(c1);
increment(c2);
}, 100)
})
});
</script>
</body>
</html>
Makefile:
static/Main.js: src/Main.elm
elm make src/Main.elm --output=static/Main.js
【问题讨论】:
标签: elm