如何同步渲染嵌入式 Elm 模块?

How to render embedded Elm module synchronously?

我正在尝试将 "HelloWorld" 模块嵌入到现有的 HTML 页面中。 我发现模块是异步呈现的(我没有得到呈现的元素 调用 "embed" 后立即执行)。

我想在现有项目中使用 Elm 并重写 JavaScript 的某些部分 在榆树。但是异步渲染使事情变得困难。

有没有同步渲染的方法?

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="app.js" type="text/javascript"></script>
</head>
<body>
<script type="text/javascript">
    var appContainer = document.createElement('div');
    Elm.HelloWorld.embed(appContainer);
    console.log('Html: ' + appContainer.innerHTML); // Will print an empty string
    setTimeout(function() {
        console.log('Html: ' + appContainer.innerHTML); // Will print "Hello, World!"
    }, 0);
</script>
</body>
</html>

HelloWorld.elm

module HelloWorld exposing (main)

import Html exposing (text)

main =
  text "Hello, World!"

更新: 删除了冗余代码。

如今,Elm 不再公开这种钩子。 您基本上有两种不同的方法,一种基于 events ,另一种基于 timing (您已经在使用的 setTimeout() 方法) .

事件驱动方法涉及 MutationObserver Api

创建一个新的 MutationObserver,您可以观察 运行 Elm 模块所在的 HTML 节点:这样,您在 DOM 上有一个钩子更新。

一个简单的检查是检查 appContainer:

的子列表
<body>
<div id="myDiv"></div>
<script type="text/javascript">
    var appContainer = document.getElementById('myDiv');
    var mo = new MutationObserver(function(mutationRecords, instance) {
        for (var i = 0; i < mutationRecords.length; i += 1) {
            if (mutationRecords[i].addedNodes.length > 0) {
                // a trivial check
                console.log('Html: ' + appContainer.innerHTML);
                // stop observing, if not needed anymore
                mo.disconnect();
            }
        }
    });
    mo.observe(appContainer, { childList: true });
    Elm.HelloWorld.embed(appContainer);
</script>
</body>

注意上面的代码是假设你的HelloWorld模块在给appContainer添加children,所以你应该修改方便:

module HelloWorld exposing (main)

import Html exposing (p, text)

main =
  p [] [ text "Hello, World!" ]