如何使用Blazor组件中的jQuery UI

时间:2019-01-20 08:07:56

标签: javascript jquery asp.net blazor

我正在研究一些Blazor示例,并且在尝试使用一些JSInterop解决方案时,我遇到了jQuery UI元素的问题。我不是熟练的Javascript程序员,但是我对.NET足够精通,所以我可能缺少一些简单的东西。我尝试使用的第一个jQuery UI组件是“可调整大小”组件,可在此处找到:https://jqueryui.com/resizable/

这是我当前的代码:

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width">
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/site.css" rel="stylesheet" />
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
    <app>Loading...</app>

    <script src="_framework/blazor.server.js"></script>
    <script>
        $( function() {
            $( "#resizable" ).resizable();
        });
    </script>
</body>
</html>

我确定问题不在于加载库,而是在加载blazor.server.js之后放置了脚本。

现在,我的 Index.cshtml 在html部分中包含以下内容:

<body>
    <div class="container-fluid">
        <div id="resizable" class="ui-widget-content">
            <div class="row row-no-gutters" style="width: 100%; height: 50%">
                <h3 class="ui-widget-header">Resizable</h3>
            </div>
        </div>
    </div>
</body>

理想情况下,这将产生可调整大小的div,但是生成的html元素不可调整大小。据我了解,Blazor JSInterop不再需要注册JS函数。我在做什么错了?

6 个答案:

答案 0 :(得分:0)

最可能的原因是计时。在DOM元素存在之前就执行jQuery函数。

您应该将JS代码注册为互操作函数,然后在OnAfterRender事件中调用它。

答案 1 :(得分:0)

是的,“ Blazor JSInterop不再需要注册JS函数”。但据我所知,您没有使用JSInterop。我认为您根本不应该使用Jquery。最重要的是,您应该创建组件来产生这种功能。 JSInterop仅应在不可能的情况下使用。 JSInterop是一个临时解决方案,用于在Blazor应用程序和DOM之间提供通信,直到Web Assembly变得足够成熟以可以直接访问DOM为止,而无需JavaScript的中介。再一次,Blazor模式,实际上是Razor组件,希望您创建组件,而不使用旧的jQuery库。

关于创建树形视图的问题堆栈溢出。它完全是用JavaScript创建的。我对开发人员的回答与我给您的相同。的确,他完全在Blazor中创建了一个树视图组件...就是这样

答案 2 :(得分:0)

问题在于时间安排:您的jQuery函数在呈现Blazor应用之前执行。

我解决此问题的方法是用命名函数(例如$(...))替换“ onready”(onBlazorReady)函数,然后从Blazor的MainLayout组件在正确的时间。

正确的时间是OnAfterRender

例如:

MainLayout.razor:

@code {
   [Inject]
   protected IJSRuntime JsRuntime { get; set; }

   protected override void OnAfterRender(bool firstRender)
   {
       if (firstRender)
           JsRuntime.InvokeVoidAsync("onBlazorReady");
   }
}

index.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width">
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/site.css" rel="stylesheet" />
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.3.1.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
    <app>Loading...</app>

    <script src="_framework/blazor.server.js"></script>
    <script>
        onBlazorReady() {
            $("#resizable").resizable();
        });
    </script>
</body>
</html>

如您所见,我正在注入IJSInterop,以便在LayoutComponent呈现后可以调用onBlazorReady JS函数。

答案 3 :(得分:0)

像这样对我很好,可以从jquery ui中添加datepicker:

剃刀组件文件。

@code {
    protected override async void OnAfterRender(bool firstRender)
    {
        await jsRuntime.InvokeVoidAsync("addDatePicker");
        base.OnAfterRender(firstRender);
    }
}

全球剃刀文件:

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Magiro.Blazor</title>
    <base href="~/" />
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
    <app>
        @(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
    </app>

    <script src="_framework/blazor.server.js"></script>
    <script>
        window.addDatePicker = () => {
            $(".datepicker").datepicker();
        }
    </script>
</body>
</html>

答案 4 :(得分:0)

通常不需要像ready这样的JQuery函数,只需将所有必需的代码放入自定义js函数中即可,该函数应在组件的ON_LOAD上运行,如上述答案中的@Sipke Schoorstra所说< / p>

答案 5 :(得分:0)

不再需要在全局索引页(ASP.NET Core 5.0 中的_Hosts.cshtml)中添加方法,该方法将使用特定于视图的逻辑和依赖项填充这些文件。至少在 v5 中,我们有 IJSObjectReference 允许我们直接从 $('table').DataTable() 文件中调用 .razor,如下所示:

<table>
    <thead>
        <tr>
            <td>Id</td>
            <td>Name</td>
        </tr>
    </thead>
    <tbody>
            <!-- your data -->
    </tbody>
</table>

@code {
    [Inject]
    protected IJSRuntime JSRuntime { get; set; }

    protected override async Task OnAfterRenderAsync(bool firstRender) {
        if (firstRender) {
            var jQuery = await JSRuntime.InvokeAsync<IJSObjectReference>("$", "table");
            await jQuery.InvokeVoidAsync("DataTable");
        }
    }
}

也可以使用匿名类型将选项传递给插件。例如,要禁用搜索,我们会在 JS 中调用

$('#example').dataTable({
  "searching": false
});

在 Blazor 中,我们创建了一个具有相同结构的匿名类型,并将其作为参数传递给 DataTable 调用:

var options = new {
    searching = false
};
await jQuery.InvokeVoidAsync("DataTable", options);