【问题标题】:Blazor enable dynamic root components / Error: Dynamic root components have not been enabled in this applicationBlazor 启用动态根组件/错误:此应用程序中未启用动态根组件
【发布时间】:2021-09-24 17:44:26
【问题描述】:

我想从 javascript 呈现 Blazor 组件。 请参阅https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-6-rc-1/“从 JavaScript 渲染 Blazor 组件”

我有一个 HTML 文件:

<script src="/_framework/blazor.server.js"></script>
<div id="counter"></div>

<script>
    async function ready() {
        let containerElement = document.getElementById('counter');
        await Blazor.rootComponents.add(containerElement, 'counter', { incrementAmount: 10 });
    }
    document.addEventListener("DOMContentLoaded", ready);
</script>

然后做

builder.Services.AddServerSideBlazor(options =>
{
    options.RootComponents.RegisterForJavaScript<Counter>("counter");
});

错误消息(JavaScript):

test.html:14 Uncaught (in promise) Error: Dynamic root components have not been enabled in this application.
    at E (blazor.server.js:1)
    at Object.add (blazor.server.js:1)
    at HTMLDocument.ready (test.html:8)

如何启用动态根组件?

【问题讨论】:

  • 我也遇到了这个问题。我会尝试分享它,看看是否有人可以帮助我们。如果有人想要样本,这是针对 Blazor WASM,但同样的错误:github.com/Swimburger/RenderBlazorFromJs

标签: javascript c# blazor


【解决方案1】:

由于文档加载和 Blazor “准备好”处理您添加组件的请求之间存在延迟,因此发生错误。

似乎没有任何官方记录的解决方案,但这样的事情是可能的

将 Blazor 更改为手动启动:

index.html

<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script src="js/script.js" defer></script>

启动 Blazor,然后尝试添加组件 - 重复直到成功

script.js

document.addEventListener("DOMContentLoaded", startBlazor)

function startBlazor() {
    Blazor
        .start()
        .then(() => {
            requestAnimationFrame(AddBlazorComponents)
        })
        .catch((error) => console.error(error));
}

let attempts = 0
const maxAttempts = 120 // arbitrary choice

function AddBlazorComponents() {
    if (attempts > maxAttempts) {
        // give up after trying too many times
        console.error("Could not load Blazor components.")
        return
    }

    const containerElement = document.querySelector('#app')
    Blazor.rootComponents.add(containerElement, 'app', {})
        .catch(reason => {
            if (reason.message === "Dynamic root components have not been enabled in this application.")
                requestAnimationFrame(AddBlazorComponents)
            else
                console.error(reason)
        })
    attempts++
}

更好的解决方案?

您可以在应用程序启动后向您的 .NET 代码添加一个 JSInterop 调用来促进这一点 - 但对于不同的托管模型会有所不同:Blazor Server / Blazor WebAssembly。

更好的方法是向 aspnetcore 存储库进行 PR,使用一种预先注册组件的方法,以便框架在准备好时加载。

2021 年 9 月 29 日更新

事实证明,有一些当前未记录的功能对此有所帮助。我从下面的@Swimburger 的github issue 复制了我的评论:

新的 JavaScript Initializer afterStarted 对于动态组件被调用(可能)太早了,但事实证明您可以传递一个初始化器来为动态组件调用 - 但它没有很好的文档或直观的恕我直言。

为了完成这项工作,我在 program.cs 中更改了这样的应用启动(添加 javaScriptInitializer: "loadApp"):

builder.RootComponents.RegisterForJavaScript&lt;App&gt;(identifier: "app", javaScriptInitializer: "loadApp");

然后,这是不直观的地方,我向我的模块(如 afterStarted)添加了一个名为 loadApp 的导出 - 但它没有被调用。

原来loadApp只有在我将它添加到window对象时才能找到,所以我将它添加到index.html

<script src="_framework/blazor.webassembly.js"></script>
<script>
    window.loadApp = function (component,params) {
        let containerElement = document.querySelector('#app')
        window.Blazor.rootComponents.add(containerElement, component, params)
    }
</script>

这感觉就像我在如何导出我的自定义初始化程序时遗漏了一些东西,或者它确实需要直接添加到window,这看起来很奇怪......

【讨论】:

  • 当我尝试这个时,我不需要请求动画帧逻辑来继续尝试。它总是在第一次尝试时起作用。 gist.github.com/Swimburger/c808f10bcb2c022c624aca233beecca1感谢您的解决方案!
  • 我还在 GitHub 上创建了一个问题,看看我们是否可以让它更直观:github.com/dotnet/aspnetcore/issues/37074
  • @Swimburger 我认为你很幸运,或者可能使用了不同的浏览器——我实际上使用你的 github 存储库编写/测试了这个,并且肯定需要重试逻辑——通常在它准备好之前大约 2 或 3 次尝试.
  • 奇怪,每次我尝试它时它总是正确加载。我在 Chrome、Edge 和 Firefox 中尝试过。我还没有在 Safari 上尝试过。我还尝试在 Chrome 中使用慢速 3G 仿真,没有任何问题。您能否提供有关您的浏览器的更多详细信息?
  • 我使用的是 Edge/Chrome/Firefox - 我向 AddBlazorComponents 添加了一个控制台日志,发现它记录了 2/3 次
猜你喜欢
  • 1970-01-01
  • 2022-01-10
  • 2021-06-24
  • 1970-01-01
  • 2019-11-03
  • 2021-02-08
  • 1970-01-01
  • 1970-01-01
  • 2010-11-20
相关资源
最近更新 更多