主题脚本在Blazor Webassembly中DOM准备就绪之前运行



我有以下代码

<body>
<app>Loading...</app>
<script src="assets/js/vendors.bundle.min.js"></script>
<script src="assets/js/main.bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/highlight.min.js"></script>
<script src="assets/js/pages/doc.script.min.js"></script>
<script src="_framework/blazor.webassembly.js" autostart="false"></script>        
</body>

main.bundle.js里面我有

jQuery(document).ready(function () {
Layout1.init();
Blazor.start();
});

当Layout1.init((;被调用,不应用哪个结果按钮事件侦听器,例如var $sidebarCompactToggle = $(".sidebar-compact-switch");

有人知道如何在DOM准备好后运行脚本吗?

更新#1

@inject IJSRuntime JSRuntime
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("Layout1.init()");
}
}
}

我得到以下错误:

crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Could not find 'init()' in 'window.Layout1'.
Error: Could not find 'init()' in 'window.Layout1'.
at https://localhost:44357/_framework/blazor.webassembly.js:1:9198
at Array.forEach (<anonymous>)

文档准备总是在ui更新之前发生,例如,当你导航到一个实际上没有导航的新页面时,blazor只更新当前页面上的元素并更新url。

您必须更改c#中HTML元素的class属性的值。

您可以使用JSInterop运行脚本。。。只需定义一个JS函数来包含初始化JS对象的代码,并从OnAfterRender(Async(方法对中调用一次即可。这些方法可以包含应该在呈现组件之后执行的代码。他们还得到一个布尔参数,指示方法的当前执行是否是第一次执行。

Blazor是一个相对较新的框架,在解决方案方面带来了新的建议。但它并不是为对抗DOM操作的JavaScript而设计的。但我们仍然可以通过互操作性访问DOM。

话虽如此,这个解决方案在一个简单的项目上对我有效:

// index.html
<script defer src="js/app.js"></script>
<script src="_framework/blazor.webassembly.js"></script>
...
// app.js
window.addEventListener('DOMContentLoaded', (event) => {
// Blazor might need some extra time to get ready,
// so we give it two more seconds
setTimeout(() => {
let hash = window.location.hash;
if (hash) {
window.scrollIntoView(hash.substring(1));
}
}, 2000);
});

但是,如果你仍然需要init函数,也许你可以"等待";具有setInterval()功能,类似于以下内容:

init: function () {
let timeId = setInterval(() => {
const ready = document.querySelector("main");
if (ready) {
clearInterval(timeId);
document.querySelectorAll(".anchor").forEach((element) => {
element.addEventListener("click", (event) => {
const url = window.location.href.split("#")[0];
window.location.assign(url + "#" + event.target.id);
});
});
}
}, 500);
}

最后,您可以从这样的特定组件中调用它(不要全局调用,尽可能避免"全球化"(:

@inject IJSRuntime JSRuntime
...
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await JSRuntime.InvokeVoidAsync("init");
await base.OnAfterRenderAsync(firstRender);
}

这不是一个完美的解决方案,但它确实奏效了。

相关内容

  • 没有找到相关文章

最新更新