如何将jQuery添加到Blazor服务器应用程序?



我试图添加一些jQuery到Blazor服务器应用程序。特别是能够自动完成表单上的InputText字段(其中id = 'CompanyName'),这是在剃刀页面(CreateNote.razor)。当我运行应用程序时,自动完成不起作用。我已经添加了警告行来测试它是否执行并且工作正常。

_Layout.cshtml:

...
</head>
<link href="TelephoneNotes.styles.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.min.js" integrity="sha256-eTyxS0rkjpLEo16uXTS0uVCS4815lc40K2iVpWDvdSY=" crossorigin="anonymous"></script>
<link href="https://tofsjonas.github.io/sortable/sortable.css" rel="stylesheet" />
<script src="https://tofsjonas.github.io/sortable/sortable.js"></script>
<script type="text/javascript">$(function () {
$("#companyName").autocomplete({
source: ["Apple", "Google", "Facebook"],
minLength: 3
})
$(document).ready(function () {
alert("test");
});
})</script>
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>

CreateNote.razor:

<EditForm Model="@newNote" OnSubmit="@InsertNote">
...
<div class="form-group row" style="padding-top: 5px;">
<label for="company" class="col-sm-2 col-form-label">
Company:
</label>
<div class="col-sm-10">
<InputText id="companyName" class="form-control" placeholder=""
@bind-Value="newNote.CompanyName" />
</div>
</div>
...
</EditForm>

更新:

我已经创建了一个init.jswwwroot文件夹:

function CompleteFormControls() {
$("#companyName").autocomplete({
source: ["Apple", "Google", "Facebook"],
minLength: 3
}

我在_Layout的底部添加了以下行。结束正文标签前的CSHTML:

<script src="/init.js"></script>

我创建了一个JSInterop类:

namespace TelephoneNotes.Services
{
using Microsoft.JSInterop;
public class JSInterop
{
private readonly IJSRuntime js;
public JSInterop(IJSRuntime js)
{
this.js = js;
}
public async ValueTask InvokeCompleteFormControls()
{
await js.InvokeVoidAsync("CompleteFormControls");
}
public void Dispose()
{
}
}
}

CreateNote.razor:

@page "/createnote"
<PageTitle>Create Note</PageTitle>
@using TelephoneNotes.Data
@inject NotesService NotesService
@implements IDisposable
@inject IJSRuntime JS
<h1>Create Note</h1>
<EditForm Model="@newNote" OnSubmit="@InsertNote">
<div class="form-group row" style="padding-top: 5px;">
<label for="company" class="col-sm-2 col-form-label">
Company:
</label>
<div class="col-sm-10">
<InputText id="companyName" class="form-control" placeholder=""
@bind-Value="newNote.CompanyName" />
</div>
</div>
<div class="form-group row" style="padding-top: 15px;">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</EditForm>
@code {
private List<string?> companyNames = new List<string?>();
private TelephoneNotes.Services.JSInterop? jsClass;
protected override async Task OnInitializedAsync()
{
jsClass = new(JS);
companyNames = await NotesService.GetCompanyNames();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await jsClass.InvokeCompleteFormControls();
}
}
public void Dispose() => jsClass?.Dispose();
}

然而,当我运行应用程序并进入创建笔记页面时,我收到以下错误:

Error: Microsoft.JSInterop.JSException: Could not find 'CompleteFormControls' ('CompleteFormControls' was undefined).

有什么建议吗?

_Host.cshtml:

@page "/"
@namespace TelephoneNotes.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
Layout = "_Layout";
}
<component type="typeof(App)" render-mode="ServerPrerendered" />
<script src="/init.js"></script>

您不能在Blazor中使用这样的Js。

什么是$( document ).ready() {}?
这意味着{}范围内的代码只会在页面DOM准备好让JS代码执行时才会渲染。

DOM在Blazor中准备好了吗?
在大多数情况下,你必须在内置的OnAfterRender函数中执行JS代码,因为在这一点上,你将确保DOM是完整的,你可以使用JS来操作前端。

执行JS函数的最佳方式是什么?

  1. wwwroot文件夹中为Js创建一个单独的文件(MyJs.js),并在那里添加Js函数。

    function CompleteFormControls ()
    {
    setTimeout(() => {
    if($("#companyName") != null){
    $("#companyName").autocomplete({
    source: ["Apple", "Google", "Facebook"],
    minLength: 3});
    }
    },500);
    }
    
  2. 添加你的Js文件'MyJs.js'在你的_Host.html正文的末尾,它应该在jquery:

    <body>
    <script src="~/lib/jquery/jquery.min.js"></script>
    <script src="~/MyJs.js"></script>
    </body>
    
  3. 创建一个类文件来表示你在MyJs.js文件中的函数:

    puplic statis class JsHelper
    {
    [DebuggerHidden]// tell VS Don't debug this function
    puplic statis aasync ValueTask CompleteFormControlsAsync(this IJSRunTime)
    {
    await js.InvokeVoidAsync("CompleteFormControls");
    }
    } 
    
  4. 在你的剃刀页面中注入IJSRuntime:

    [Inject] private IJSRuntime Js {get; set;}
    protected override Task OnAfterRenderAsync(bool firstRender)
    {
    if(firstRender)
    {
    await Js.CompleteFormControlsAsync();
    }
    }
    

注意:您也可以替换OnAfterRenderAsync并使用一些事件,如Click事件,因为在这种情况下,您可以确定DOM也完成了渲染。

将javascript放在body标签的末尾。您放置它的当前位置$("#companyName")将为空。组件必须在javascript执行之前加载。

<html>
<body>
<Your Components will be here>
<script type="text/javascript">$(function () {
$("#companyName").autocomplete({
source: ["Apple", "Google", "Facebook"],
minLength: 3
})
$(document).ready(function () {
alert("test");
});
})</script>
<body>
</html>

Pages/_Layout.cshtml中,将以下代码段与JS脚本一起添加到正文的末尾:

<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="js/init.js"></script>

在这种情况下,你的JS脚本将在wwwroot/JS文件夹

在CreateNote.razor:

IJSRuntime _js
//other code here
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await _js.InvokeVoidAsync("CompleteFormControls");
}
}

Blazor不理解查询选择器'$',您需要将其替换为关键字document

最新更新