如何不使用JS打开新窗口

问题描述 投票:0回答:7

在 blazor 中,我使用

NavigationManager.NavigateTo(url)
来更改窗口位置,但是如何使用它来打开具有指定 URL 的新选项卡,而无需在
OnAfterRenderAsync()

上调用 JS
c# signalr blazor
7个回答
50
投票

截至 2022 年 6 月 1 日,目前无法直接使用纯 Blazor 执行此操作,您需要使用 JSInterop。幸运的是,这很容易做到。在

.razor
文件顶部添加

@inject IJSRuntime JSRuntime;

然后像这样使用它

await JSRuntime.InvokeAsync<object>("open", url, "_blank");

注意,

IJSRuntime
接口本身只提供了一个
InvokeAsync<TValue>
方法,
JSRuntimeExtensions
类为
IJSRuntime
提供了扩展方法,可以直接调用不带返回值的方法:
InvokeVoidAsync

await JSRuntime.InvokeVoidAsync("open", url, "_blank");

25
投票

以前,此代码有效。

await _jsRuntime.InvokeVoidAsync("open", new object[2] { url, "_blank" });

目前,它会导致未捕获的异常:

> "TypeError: Converting circular structure to JSON

我发现这里解释了这种行为(https://github.com/dotnet/aspnetcore/issues/16632):

这是因为 window.open 返回一个 WindowProxy 对象(参见 https://developer.mozilla.org/en-US/docs/Web/API/Window/open)。 WindowProxy 不可 JSON 序列化,因此不能用作返回 .NET 代码的值。

要解决这个问题,不要直接调用window.open,而是调用JS 您自己的函数,要么不返回任何内容,要么返回某些内容 这是 JSON 可序列化的。

根据上述建议,我将以下内容添加到index.html:

<script>
    window.blazorOpen = (args) => {
        window.open(args);
    };
</script>

并修改了我的 C# 代码隐藏调用以传递窗口参数:

await _jsRuntime.InvokeVoidAsync("blazorOpen", new object[2] { url, "_blank" });

我们现在通过丢弃 window.open 返回的 WindowProxy 对象来有效地避免该问题,该对象以前返回到 InvokeVoidAsync 并且 .NET 尝试(不成功)处理。


10
投票

使用时你会得到

TypeError: Converting circular structure to JSON

await _jsRuntime.InvokeVoidAsync("open", new object[2] { url, "_blank" });

await _jsRuntime.InvokeAsync<object>("open", url, "_blank");

这是因为

window.open
返回一个
WindowProxy
对象(参见 https://developer.mozilla.org/en-US/docs/Web/API/Window/open)。
WindowProxy
不可 JSON 序列化,因此不能用作 .NET 代码的返回值。

摘自参见此处

要使用 javascript 函数解决此问题,我使用以下代码

await JSRuntime.InvokeVoidAsync("eval", $"let _discard_ = open(`{url}`, `_blank`)");

4
投票

只需使用常规链接

<a href="@Url" target="_blank">@UrlDescription</a>

3
投票

根据 API 的最新更改,这里是工作解决方案,您可以将任何自定义对象属性添加到 URL,如下所示:

    /// <summary>
    /// Show Link
    /// </summary>
    /// <returns></returns>
    private async Task ShowLink()
    {
        if (this.selectedItem != null)
        {
            string url = $"https://example.com/sites/" + this.selectedItem.Id + "/SitePages/Reports/somepage.aspx";
            //NavigationManager.NavigateTo(url, false);//opens the new page on same browser tab
            string[] values = { url, "_blank" };
            CancellationToken token = new CancellationToken(false);
            await JSRuntime.InvokeAsync<object>("open", token, values);//opens the link in new browser tab
        }
    }

2
投票

最好的方法是:

<NavLink class="MyCssClass" 
         target="_blank" 
         href="https://www.google.com">
         Google in new window
</NavLink>

0
投票

.net 7+

你必须使用

await JSRuntime.InvokeVoidAsync("open", url, "_blank");

如果您使用

JSRuntime.InvokeAsync<object>
,则会导致错误:

blazor.server.js:1  [2024-04-16T07:48:04.751Z] Error: Microsoft.JSInterop.JSException: Converting circular structure to JSON
    --> starting at object with constructor 'Window'
    --- property 'window' closes the circle
TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Window'
    --- property 'window' closes the circle
    at JSON.stringify (<anonymous>)
    at D (https://localhost:44326/_framework/blazor.server.js:1:5345)
    at https://localhost:44326/_framework/blazor.server.js:1:3541
   at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](Int64 targetInstanceId, String identifier, Object[] args)
© www.soinside.com 2019 - 2024. All rights reserved.