ASP.NET Core Blazor 4:高级Blazor特性

一文看懂Blazor 和 ASP.NET Core MVC 异同 阅读详情

  本章解释 Blazor 如何支持 URL 路由,以便通过一个请求显示多个组件。展示如何设置路由系统、如何定义路由以及如何在布局中创建公共内容。
  本章还介绍了组件的生命周期,它允许组件积极地参与 Blazor 环境,这在开始使用 URL 路由特性时尤为重要。最后,本章解释了组件在前面章节描述的父!子关系之外的不同交互方式。
  路由特性允许组件响应 URL 中的更改,而不需要新的 HTTP 连接。生命周期特性允许组件定义在执行应用程序时调用的方法,交互特性提供了在组件之间以及与其他JavaScript 代码进行通信的有用方法。

1 准备工作

  继续使用上一章项目。

2 使用组件的路由

  Blazor 支持根据 ASPNET Core路由系统选择要显示给用户的组件,使应用程序通过显示不同的 Razor 组件来响应 URL中的变化。首先,给 Blazor 文件夹添加一个名为 Routed.razor 的 Razor 组件,内容如代码清单所示。

<Router AppAssembly="typeof(Startup).Assembly">
    <Found>
        <RouteView RouteData="@context" />
    </Found>
    <NotFound>
        <h4 class="bg-danger text-white text-center p-2">
            Not Matching Route Found
        </h4>
    </NotFound>
</Router>

  Router 组件包含在 ASP.NET Core 中,提供了 Blazor 和 ASP.NET Core 路由特性之间的链接 Router 是一个通用模板组件,它定义了 Found 和 NotFound 部分。
  Router 组件需要 AppAssembly 属性,该属性指定要使用的.NET 程序集。对于大多数项目这是当前的程序集,它的指定如:AppAssembly="typeof(Startup).Assembly"。Router 组件的 Found 属性类型是 RenderFragment<RouteData>,它通过 RouteData 属性传递给RouteView 组件,如下所示:<RouteView RouteData="@context" />。RouteView 组件负责显示与当前路由匹配的组件,以及通过布局显示公共内容。NotFound 属性的类型是 RenderFragment,没有泛型类型参数,在当前路由找不到组件时显示内容部分。

2.1 准备 Blazor 页

  单个组件可以显示在现有的控制器视图和 Blazor 页面中。但是在使用组件路由时,最好创建一组与 Blazor 不同的 URL,因为 URL 被支持的方式是有限的,并且会导致复杂的解决方案。将一个名为 _Host.cshtml 的 Razor Pages 添加到 Pages 文件夹,并添加如代码清单所示的内容。

@page "/"
@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="/lib/twitter-bootstrap/css/bootstrap.min.css" rel="stylesheet" />
    <base href="~/" />
</head>
<body>
    <div class="m-2">
        <component type="typeof(MyAdvanced.Blazor.Routed)" render-mode="Server" />
    </div>
    <script src="_framework/blazor.server.js"></script>
</body>
</html>

  修改配置,以当请求与现有 URL 路由不匹配时使用 _Host.cshtml 文件作为回退,如代码清单所示。

app.UseEndpoints(endpoints =>
            {
                ......
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });

  MapFallbackToPage 方法将路由系统配置为使用 Host页面,作为处理不匹配请求的最后手段。

2.2 向组件添加路由

  组件声明应该使用 @page 指令显示的 URL。给 PeopleList 组件添加了@page 指令@page "/people"。指令意味着为 http://localhost:5000/people URL 显示 PeopleList 组件。组件可使用多个@page指令声明对多个路由的支持。将 @page 指令添加到 DepartmentLis 组件以支持两个 URL @page "/departments"、@page "/depts" 。
  要查看基本的 Razor 组件路由特性的工作情况,请求 http://localhost:5000/people 和 http://localhost:5000/depts。每个 URL, 显示应用程序中的一个组件。设置默认组件路由
  Starup 类中的请求设置了回退路由,应用程序需要默认 URL http:/localhost:5000 显示的组件,不然会报找不到路由。在 Blazor 文件夹的 PeopleListrazor 文件中定义默认路由 @page "/"就可以了。

2.3 在路由组件之间导航

  基本的路由配置已经就绪,但使用路由比独立组件的优势还不明显。下面使用 NavLink 组件改进,它呈现连接到路由系统的锚元素。代码清单将 NavLink 添加到 PeopleList 组件。

<NavLink class="btn btn-primary" href="/depts">Departments</NavLink>

  NavLink 组件是使用 URL 配置的,而不是组件、页面或动作名称。本例中的 NavLink 导航到 Departmentist 组件的 @page 指令所支持的 URL。
  导航也可以通过编程方式执行,这在组件响应事件然后需要导航到不同的URL时非常有用,如下在 Blazor 文件夹的 DepartmentList.razor 文件中以编程方式导航。

......
    
<button class="btn btn-primary" @onclick="HandleClick">People</button>

@code
{
    ......
        
    [Inject]
    public NavigationManager NavManager { get; set; }
    public void HandleClick() => NavManager.NavigateTo("/people");
}

  NavigationManager 类提供对导航的编程访问。以下描述了 NavigationManager 类提供的最重要成员。

名称描述
NavigateTo(url)此方法导航到指定的 URL,而不发送新的 HTTP 请求
ToAbsoluteUri(path)此方法将一个相对路径转换为一个完整的 URL
ToBaseRelativePath(url)此方法从完整的 URL 中获取相对路径
LocationChanged位置更改时触发此事件
Uri此属性返回当前 URL

  NavieadionMangst 类作为服务提供,并通过 Inject 属性被 Razor 组件接收,NavManager.NavigateTo 方法导航到一个 URL,该 URL 由 PeopleList 组件处理。
  请求 http://localhost:5000/people。单击 Departments 链接,该链接样式化为一个按钮。Departmenlist 组件将息示出来,单击 People 链接,将返回到 PeopleList 组件。

2.4 接收路由数据

  组件可以通过使用 Parameter 属性修饰属性来接收段变量。为了便于演示,为 Blazor 文件添加一个名为 PersonDisplay.razor 的 Razor 组件。

@page "/person"
@page "/person/{id:long}"

<h5>Editor for Person: @Id</h5>
<NavLink class="btn btn-primary" href="/people">Return</NavLink>

@code
{
    [Parameter]
    public long Id { get; set; } = 0;
}

  使用 NavLink 组件为 PeopleList 组件显示的每个 Person 对象创建导航链接。

@page "/"
@page "/people"

<TableTemplate RowType="Person" RowData="People"
               Highlight="@(p=>p.Location.City)" SortDirection="@(p=>p.Surname)">
    <Header>
    <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Dept</th>
        <th>Location</th>
        <td></td>
    </tr>
    </Header>
    <RowTemplate Context="p">
        <td>@p.PersonId</td>
        <td>@p.Surname, @p.Firstname</td>
        <td>@p.Department.Name</td>
        <td>@p.Location.City, @p.Location.State</td>
        <td>
            <NavLink class="btn btn-sm btn-info" href="@GetEditUrl(p.PersonId)">
                Edit
            </NavLink>
        </td>
    </RowTemplate>
</TableTemplate>

<NavLink class="btn btn-primary" href="/depts">Departments</NavLink>

@code
{
    [Inject]
    public DataContext Context { get; set; }

    public IEnumerable<Person> People => Context.People
            .Include(p => p.Department)
            .Include(p => p.Location);

    [Inject]
    public NavigationManager NavManager { get; set; }
    public void HandleClick() => NavManager.NavigateTo("/people");

    public string GetEditUrl(long id) => $"/person/{id}";
}

  Razor 组件不支持在属性值中混合静态内容和 Razor 表达式。相反,前面定义了 GetEditUrl 方法来为每个 Person 对象生成导航 URL,调用该方法来生成 NavLink href 属性的值。
  请求 http://localhost:5000/people,然后单击其中一个 Edit 按钮。浏览器导航到新的 URL 而不重新加载 HTML 文档,并显示 PersonDisplay 组件生成的占位符内容,显示了组件如何从路由系统中接收数据。

2.5 使用布局定义公共内容

  布局是为 Razor 组件提供通用内容的模板组件。要创建布局,给 Blazor 文件夹添加一个名为NavLayout.razor 的 Razor 组件。

@inherits LayoutComponentBase

<div class="container-fluid">
    <div class="row">
        <div class="col-3">
            @foreach (string key in NavLinks.Keys)
            {
                <NavLink class="btn btn-outline-primary btn-block"
                         href="@NavLinks[key]"
                         ActiveClass="btn-primary text-white"
                         Match="NavLinkMatch.Prefix">
                    @key
                </NavLink>
            }
        </div>
        <div class="col">
            @Body
        </div>
    </div>
</div>

@code
{
    public Dictionary<string, string> NavLinks = new Dictionary<string, string>
        {{"People","/people"}, {"Departments", "/depts"},{"Details", "/person"}};
}

  布局使用 @inherits 表达式指定 LayoutComponentBase 类作为从Razor 组件中生成的类的基类。LayoutComponentBase 类定义了一个名为 Body 的 RenderFragment 类,用于指定布局中显示的公共内容中的组件内容。
  在本例中,布局组件创建了一个网格布局,该布局为应用程序中的每个组件显示一组 NavLink 组件。NavLink 组件配置了两个新属性。

  • ActiveClass:此属性指定一个或多个 CSS 类,当前 URL与 href 属性值匹配时,由 NavLink 组件呈现的锚元素将添加到这些 CSS 类中
  • Match:此属性指定如何使用来自 NavLinkMatch 枚举的值将当前 URL 匹配到 href属性;这些值是Prefix(如果 href 匹配 URL 的开头,则认为是匹配的)和 All(要求整个 URL 相同)

  NavLink 组件配置为使用前缀匹配,并当有匹配时,添加它们呈现给引导程序 btn-primary 和 text-white 类的锚元素。应用布局
  有三种方法可以应用布局。组件可以使用 @layout 表达式选择自己的布局。父组件可通过将子组件包装到内置的 LayoutView 组件中,来为其子组件使用布局。通过设置 RouteView 组件的 DefaultLayout 属性,可将布局应用于所有组件,如下在 Blazor 文件夹的 Routed.razor文件中应用布局。

<Found>
    <RouteView RouteData="@context" DefaultLayout="typeof(NavLayout)" />
</Found>

  请求 http://localhost:5000/people,该布局与 PeopleList 组件呈现的内容一起显示。布局左侧的导航按钮可用于在应用程序中导航。

3 理解组件生命周期方法

  Razor 组件具有定义良好的生命周期,用组件可以实现的方法来表示,以接收关键转换的通知。

名称描述
OnInitialized()、OnInitializedAsync()这些方法在组件第一次初始化时调用
OnParametersSet()、OnParametersSetAsync()这些方法在应用通过 Parameter 属性修饰的属性值后调用
ShouldRender()此方法在呈现组件的内容之前调用,以更新呈现给用户的内容。如果该方法返回false,则组件的内容将不呈现,更新将被抑制。此方法不会取消组件的初始呈现
OnAferRender(first)、OnAfterRenderAsync(first)在呈现组件的内容之后调用此方法。当 Blazor 为组件执行初始渲染时,bool参数为 true

  使用 OnInitialized 或 OnParameterSet 方法都可用于设置组件的初始状态。上一节定义的布局没有处理默认的 URL,因为 NavLink 组件只匹配一个 URL。对于 DepartmentList 组件也存在同样的问题,可以使用 /departments 和 /depts 路径请求该组件。
  创建匹配多个 URL 的组件需要使用生命周期方法。要了解原因,请为 Blazor 文件夹添加一个名为 MultiNavLink.razor 的 Razor 组件。

<a class="@ComputedClass" @onclick="HandleClick" href="">
    @ChildContent
</a>

@code
{
    [Inject]
    public NavigationManager NavManager { get; set; }
    [Parameter]
    public IEnumerable<string> Href { get; set; }
    [Parameter]
    public string Class { get; set; }
    [Parameter]
    public string ActiveClass { get; set; }
    [Parameter]
    public NavLinkMatch? Match { get; set; }

    public NavLinkMatch ComputedMatch
    {
        get => Match ??
        (Href.Count() == 1 ? NavLinkMatch.Prefix : NavLinkMatch.All);
    }
    
    [Parameter]
    public RenderFragment ChildContent { get; set; }
    public string ComputedClass { get; set; }
    
    public void HandleClick()
    {
        NavManager.NavigateTo(Href.First());
    }

    private void CheckMatch(string currentUrl)
    {
        string path = NavManager.ToBaseRelativePath(currentUrl);
        path = path.EndsWith("/") ? path.Substring(0, path.Length - 1) : path;
        bool match = Href.Any(href => ComputedMatch == NavLinkMatch.All
                ? path == href : path.StartsWith(href));
        ComputedClass = match ? $"{Class} {ActiveClass}" : Class;
    }

    protected override void OnParametersSet()
    {
        ComputedClass = Class;
        NavManager.LocationChanged += (sender, arg) => CheckMatch(arg.Location);
        Href = Href.Select(h => h.StartsWith("/") ? h.Substring(1) : h);
        CheckMatch(NavManager.Uri);
    }
}

  该组件的工作方式与常规 NavLink 相同,但接收一组路径来匹配。组件依赖于 OnParametersSet 生命周期方法,因为需要进行一些初始设置,而只有在为用 Parameter 属性修饰的属性分配了信之后,才能执行这些初始设置,如提取单个路径。
  此组件通过侦听由 NavigationManager 类定义的 LocationChanged 事件来响应当前 URL 中的更改。事件的 Location 属性为组件提供当前 URL, 该 URL 用于更改锚元素的类。
  在 Blazor 文件夹的 NavLayout.razor 文件中应用新组件。

@foreach (string key in NavLinks.Keys)
{
    <MultiNavLink class="btn btn-outline-primary btn-block" href="@NavLinks[key]"
                  ActiveClass="btn-primary text-white">
        @key
    </MultiNavLink>
}
@code
{
    public Dictionary<string, string[]> NavLinks = new Dictionary<string, string[]>
    {
        {"People", new string[] {"/people", "/" } },
        {"Departments", new string[] {"/depts", "/departments" } },
        {"Details", new string[] { "/person" } }
     };
}

  并请求 http://localhost:5000 和 http://localhost:5000/departments。这两个URL都可以识别,相应的导航按钮高亮显示。对异步任务使用生命周期方法
  生命周期方法对于执行可能在呈现组件的初始内容之后完成的任务也很有用,例如查询数据库。在 Blazor 文件夹的 PersonDisplay.razor 文件中通过生命周期方法查询数据。

@page "/person"
@page "/person/{id:long}"

@if (Person == null)
{
    <h5 class="bg-info text-white text-center p-2">Loading...</h5>
}
else
{
    <table class="table table-striped table-bordered">
        <tbody>
            <tr><th>Id</th><td>@Person.PersonId</td></tr>
            <tr><th>Surname</th><td>@Person.Surname</td></tr>
            <tr><th>Firstname</th><td>@Person.Firstname</td></tr>
        </tbody>
    </table>
}

<button class="btn btn-outline-primary" @onclick="@(()=>HandleClick(false))">
    Previous
</button>
<button class="btn btn-outline-primary" @onclick="@(()=>HandleClick(true))">
    Next
</button>

@code
{
    [Inject]
    public DataContext Context { get; set; }
    [Inject]
    public NavigationManager NavManager { get; set; }
    [Parameter]
    public long Id { get; set; } = 0;
    public Person Person { get; set; }

    protected async override Task OnParametersSetAsync()
    {
        await Task.Delay(1000);
        Person = await Context.People.FirstOrDefaultAsync(p => p.PersonId == Id)
            ?? new Person();
    }
    public void HandleClick(bool increment)
    {
        Person = null;
        NavManager.NavigateTo($"/person/{(increment ? Id + 1 : Id - 1)}");
    }
}

  直到设置了参数值,组件才能查询数据库,因此在 OnParametersSetAsync 方法中获得 Person 属性的值。因为数据库是与 ASP.NET Core 服务器一起运行的,在查询数据库之前添加了一秒钟的延迟,以帮助强调组件的工作方式。
  在查询完成前,Person 属性的值为 null,这时它是表示查询结果的对象,或者如果查询没有生成结果,它就是一个新的 Person 对象。当 Person 对象为空时,将显示加载消息。
  重启ASP.NET Core,并请求 http://ocalhost:5000。单击表中显示的一个 Edit 按钮,PersonDisplay组件显示数据的摘要。单击 Previous 和 Next 按钮,以查询具有相邻主键值的对象。

4 管理组件的交互

  大多数组件通过参数和事件来工作,允许通过用户的交互来驱动应用程序中的更改。Blaz0还提供了用于管理与组件交互的高级选项。

4.1 使用子组件的引用

  父组件可以获得对子组件的引用,并可使用子组件定义的属性和方法。将禁用状态添加到 MultiNavLink 组件。

<a class="@ComputedClass" @onclick="HandleClick" href="">
    @if (Enabled)
    {
        @ChildContent
    }
    else
    {
        @("Disabled")
    }
</a>

@code
{
    [Inject]
    public NavigationManager NavManager { get; set; }

    [Parameter]
    public IEnumerable<string> Href { get; set; }

    [Parameter]
    public string Class { get; set; }

    [Parameter]
    public string ActiveClass { get; set; }

    [Parameter]
    public string DisabledClasses { get; set; }

    [Parameter]
    public NavLinkMatch? Match { get; set; }

    public NavLinkMatch ComputedMatch
    {
        get => Match ??
        (Href.Count() == 1 ? NavLinkMatch.Prefix : NavLinkMatch.All);
    }

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    public string ComputedClass { get; set; }


    public void HandleClick()
    {
        NavManager.NavigateTo(Href.First());
    }

    private void CheckMatch(string currentUrl)
    {
        string path = NavManager.ToBaseRelativePath(currentUrl);
        path = path.EndsWith("/") ? path.Substring(0, path.Length - 1) : path;
        bool match = Href.Any(href => ComputedMatch == NavLinkMatch.All
                ? path == href : path.StartsWith(href));
        if (!Enabled)
        {
            ComputedClass = DisabledClasses;
        }
        else
        {
            ComputedClass = match ? $"{Class} {ActiveClass}" : Class;
        }
    }

    protected override void OnParametersSet()
    {
        ComputedClass = Class;
        NavManager.LocationChanged += (sender, arg) => CheckMatch(arg.Location);
        Href = Href.Select(h => h.StartsWith("/") ? h.Substring(1) : h);
        CheckMatch(NavManager.Uri);
    }

    private bool Enabled { get; set; } = true;

    public void SetEnabled(bool enabled)
    {
        Enabled = enabled;
        CheckMatch(NavManager.Uri);
    }
}

  在 Blazor 文件夹的 NavLayout.razor 文件中保留引用,更新共享布局,以便保留对 MultiNavLink 组件和一个按钮的引用该按钮用于切换其 Enabled 属性值。

@inherits LayoutComponentBase

<div class="container-fluid">
    <div class="row">
        <div class="col-3">
            @foreach (string key in NavLinks.Keys)
            {
                <MultiNavLink class="btn btn-outline-primary btn-block"
                              href="@NavLinks[key]"
                              ActiveClass="btn-primary text-white"
                              DisabledClasses="btn btn-dark text-light btn-block disabled"
                @ref="Refs[key]">
                    @key
                </MultiNavLink>
            }
            <button class="btn btn-secondary btn-block mt-5 " @onclick="ToggleLinks">
                Toggle Links
            </button>
        </div>
        <div class="col">
            @Body
        </div>
    </div>
</div>

@code
{

    public Dictionary<string, string[]> NavLinks = new Dictionary<string, string[]>
    {
        {"People", new string[] {"/people", "/" } },
        {"Departments", new string[] {"/depts", "/departments" } },
        {"Details", new string[] { "/person" } }
     };

    public Dictionary<string, MultiNavLink> Refs
        = new Dictionary<string, MultiNavLink>();

    private bool LinksEnabled = true;

    public void ToggleLinks()
    {
        LinksEnabled = !LinksEnabled;
        foreach (MultiNavLink link in Refs.Values)
        {
            link.SetEnabled(LinksEnabled);
        }
    }
}

  通过添加 @ref 属性,并指定应该为组件分配的字段或属性的名称,可以创建对组件的引用。由于 MultiNavLink 组件是在由 Dictionary 驱动的 @foreach 循环中创建的,因此保留引用的最简单方法也是在 Dictionary 中,如下所示:@ref="Refs[key]"。在创建每个 MultiNavLink 组件时,它添加到 Refs 字典中。Razor 组件编译成标准的 C#类,这意味着 MultiNavink 组件的集合就是 MultiNavLink 对象的集合。
  重启ASP.NET Core,并请求 http://localhost:5000。然后单击 Toggle Links 按钮。事件处理程序调用 ToggleLinks 方法,它为每个 MultiNavLink 组件设置 Enabled 属性的值。

4.2 与来自其他代码的组件交互

  组件可被 ASP.NET Core 应用程序中的其他代码使用,允许复杂项目的各个部分之间进行更丰富的交互。如下修改了 MultiNavLink 组件中的方法,以便可以由 ASP.NET Core 应用程序的其他部分调用,来启用和禁用导航。

public void SetEnabled(bool enabled)
{
    InvokeAsync(() =>
    {
        Enabled = enabled;
        CheckMatch(NavManager.Uri);
        StateHasChanged();
    });
}

  组件提供了在 Blazor环境外部调用的代码中使用的两个方法:InvokeAsync(func) 方法用于调用 Blazor 环境中的一个函数,以确保正确地处理更改。当应用所有更改时,将调用 StateHasChanged() 方法,触发 Blazor 更新并确保更改反映在组件的输出中。
  要创建将在整个应用程序中可用的服务,请创建 Services 文件夹,并将一个名为ToggleService.cs 的类文件添加到其中。

using MyAdvanced.Blazor;
using System.Collections.Generic;
using Microsoft.JSInterop;

namespace MyAdvanced.Services
{
    public class ToggleService
    {
        private List<MultiNavLink> components = new List<MultiNavLink>();
        private bool enabled = true;

        public void EnrolComponents(IEnumerable<MultiNavLink> comps)
        {
            components.AddRange(comps);
        }

        [JSInvokable]
        public bool ToggleComponents()
        {
            enabled = !enabled;
            components.ForEach(c => c.SetEnabled(enabled));
            return enabled;
        }
    }
}

  此服务管理一个组件集合,并在调用其 ToggleComponents 方法时对所有组件调用 SetEnabled 方法。 更新 Startup.cs 应用程序配置,将 Toggleservice 类配置为单例服务。

services.AddSingleton<Services.ToggleService>();

  在 Blazor 文件夹的 NavLayout.razor 文件中使用服务。

@inherits LayoutComponentBase
@using MyAdvanced.Services

......

@code
{

    [Inject]
    public ToggleService Toggler { get; set; }

    public Dictionary<string, string[]> NavLinks = new Dictionary<string, string[]>
    {
        {"People", new string[] {"/people", "/" } },
        {"Departments", new string[] {"/depts", "/departments" } },
        {"Details", new string[] { "/person" } }
     };

    public Dictionary<string, MultiNavLink> Refs
        = new Dictionary<string, MultiNavLink>();

    private bool LinksEnabled = true;

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            Toggler.EnrolComponents(Refs.Values);
        }
    }

    public void ToggleLinks()
    {
        Toggler.ToggleComponents();
    }
}

  如上一节所述,组件引用只有在内容呈现之后才可用。代码使用 OnAferRender 生命周期方法向服务注册组件引用,服务是通过依赖项注入接收的。
  最后一步是从 ASP.NET Core 应用程序的不同部分使用服务。每次处理请求时,在 Controllers 文件夹的 HomeController.cs 文件中,向调用 ToggleService 的主控制器添加了一个简单的操作方法。

private DataContext context;
private ToggleService toggleService;

public HomeController(DataContext dbContext,ToggleService ts)
{
    context = dbContext;
    toggleService = ts;
}
public string Toggle() =>
    $"Enabled: { toggleService.ToggleComponents() }";

  重启 ASP.NET Core 并请求 http://localhost:5000。打开一个单独的浏览器窗口并请求http:/localhost:5000/controllers/home/toggle。当 ASP.NET Core 应用程序处理第二个请求时。操作方法将使用服务来切换导航按钮的状态。每次请求 /controllers/home/toggle 时,导航按钮的状态将发生变化。

4.3 使用 JavaScript 与组件交互

  Blazor 提供了一系列在 JavaScript 和服务器端 C#代码之间交互的工具,如下所述。1.从组件中调用 JavaScript 函数
  在 wwwoot 文件夹中添加一个名为 interop.js。

function addTableRows(colCount) {
    let elem = document.querySelector("tbody");
    let row = document.createElement("tr");
    elem.append(row);
    for (let i = 0; i < colCount; i++) {
        let cell = document.createElement("td");
        cell.innerText = "New Elements"
        row.append(cell);
    }
}

  javascript 代码使用浏览器提供的 API 来定位 tbody 元素,该元素表示表的主体,并添加一个新行,其中包含由函数参数指定的单元格数量。
  要将 JavaScript 文件合并到应用程序中,在 Pages 文件夹的 _Host.cshtml Rozar Pages 中添加元素,该页面配置为将 Blazor 应用程序交付到浏览器的回退页面。

<script src="~/interop.js"></script>

  在 Blazor文件夹的 PersonDisplay.razor 文件中调用 JavaScrpt 函数。

@page "/person"
@page "/person/{id:long}"

@if (Person == null)
{
    <h5 class="bg-info text-white text-center p-2">Loading...</h5>
}
else
{
    <table class="table table-striped table-bordered">
        <tbody>
            <tr><th>Id</th><td>@Person.PersonId</td></tr>
            <tr><th>Surname</th><td>@Person.Surname</td></tr>
            <tr><th>Firstname</th><td>@Person.Firstname</td></tr>
        </tbody>
    </table>
}

<button class="btn btn-outline-primary" @onclick="@HandleClick">
    Invoke JS Funtion
</button>


@code
{
    [Inject]
    public DataContext Context { get; set; }
    [Inject]
    public NavigationManager NavManager { get; set; }
    [Inject]
    public IJSRuntime JSRuntime { get; set; }
    [Parameter]
    public long Id { get; set; } = 0;
    public Person Person { get; set; }

    protected async override Task OnParametersSetAsync()
    {
        //await Task.Delay(1000);
        Person = await Context.People.FirstOrDefaultAsync(p => p.PersonId == Id)
            ?? new Person();
    }
    public async Task HandleClick()
    {
        await JSRuntime.InvokeVoidAsync("addTableRows", 2);
    }
}

  调用 Javascipt 函数是通过 IJSRuntime 接口完成的,该接口由组件通过依赖项注入接收。服务是作为Blazor 配置的一部分自动创建的,并提供表中描述的方法。

名称描述
InvokeAsync(name, args)此方法使用提供的参数调用指定的函数。结果类型由泛型类型参数指定
InvokeVoidAsync(name, args)此方法调用一个不生成结果的函数

  在代码清单中,使用 InvokeVoidAsync 方法调用 JavaScript 函数 addTableRows,为函数参数提供一个值。重启 ASP.NET Core,导航到 http:/localhost:5000/person/1,然后单击 Invoke JS Funtion 按钮。Blazor 将调用 JavaScript 函数,该函数将在表的末尾添加一行。2.保留对 HTML 元素的引用
  Razor 组件可以保留对它们创建的 HTML 元素的引用,并将这些引用传递给 JavaScript 代码。在wwwroot 文件夹的 interop.js 文件中定义参数,使其对通过参数接收的 HTML 元素进行操作。

function addTableRows(colCount, elem) {
    //let elem = document.querySelector("tbody");
    let row = document.createElement("tr");
    elem.parentNode.insertBefore(row, elem);
    for (let i = 0; i < colCount; i++) {
        let cell = document.createElement("td");
        cell.innerText = "New Elements"
        row.append(cell);
    }
}

  在 Blazor 文件夹的 PersonDisplay.razor 文件中保留保留了对它创建的一个 HTML 元素的引用,并将其作为参数传递给 JavaScript 函数。

<tr @ref="RowReference"><th>Surname</th><td>@Person.Surname</td></tr>
public ElementReference RowReference { get; set; }
public async Task HandleClick()
{
    await JSRuntime.InvokeVoidAsync("addTableRows", 2, RowReference);
}

  @ref 属性将 HTML 元素分配给一个属性,该属性的类型必须是 ElementReference。重启ASP.NET Core,请求 http:/localhost:5000/person/1,然后单击 Invoke Js Function 按钮。HementReference 属性的值作为参数通过 InvokeVoidAsync 方法传递给 Javascript 函数。3.从 JavaScript 调用组件方法
  从JavaScript 调用 C#方法的基本方法是使用静态方法。 在 Blazor 文件夹的 MultiNavLink.razor 文件中引入静态成员。

[JSInvokable]
public static void ToggleEnabled() => ToggleEvent.Invoke(null, new EventArgs());
private static event EventHandler ToggleEvent;
protected override void OnInitialized()
{
    ToggleEvent += (sender, args) => SetEnabled(!Enabled);
}

  静态方法必须使用 JSInvokable 属性进行修饰,然后才能从JavaScript 代码中调用它们。使静态方法的主要限制是难以更新单个组件,因此定义了组件的每个实例都会处理的一个静态事件,该事件命名为 ToggleEvent,它由将从 JavaScript 调用的静态方法触发。为了监听事件,使用 Onnitiaized 生命周期事件。当接收到事件时,组件的启用状态通过实例方法 SetEnabled 来切换,该方法使用在 Blazor 之外进行更改时所需的 InvokeAsync 和 StateHasChanged 方法。
  在wwwroot 文件夹的 interop.js 文件中添加函数,该函数创建了一个 buton 元素,该元素在单击时调用静态 C#方法。

function createToggleButton() {
    let sibling = document.querySelector("button:last-of-type");
    let button = document.createElement("button");
    button.classList.add("btn", "btn-secondary", "btn-block");
    button.innerText = "JS Toggle";
    sibling.parentNode.insertBefore(button, sibling.nextSibling);
    button.onclick = () => DotNet.invokeMethodAsync("MyAdvanced","ToggleEnabled");
}

  新函数定位一个现有 button 元素,并在其后面添加一个新按钮。当单击按钮时,调用组件方法,如下所示: DotNet.invokeMethodAsync。
  注意用于 C#方法的 JavaScript 函数的大小写很重要:它是 DoNet,后面是句点,后面是imvokeMethodAsync,后面是小写的i,参数是程序集的名称和静态方法的名称。组件的名称不是必需的。
  上述代码中函数寻找的按钮元素只有在 Blazor 为用户呈现了内容之后才可用。由于这个原因,如下 NavLayout 组件定义的 OnAheRenderAsync 方法中深加了一条语句,仅在内容呈现后才调用JavaScipt 的函数数。NavLayout 组件是 MuitiNavLink 组件的父组件,当调用静态方法时,MuitiNavLink组件会受到影响,并允许确保Javaseript函数贝调用一次。
  在Blazor 文件夹的 NavLayout.razor文件中调用 JavaScript 函数。

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

    [Inject]
    public ToggleService Toggler { get; set; }

    public Dictionary<string, string[]> NavLinks = new Dictionary<string, string[]>
    {
        {"People", new string[] {"/people", "/" } },
        {"Departments", new string[] {"/depts", "/departments" } },
        {"Details", new string[] { "/person" } }
     };

    public Dictionary<string, MultiNavLink> Refs
        = new Dictionary<string, MultiNavLink>();

    private bool LinksEnabled = true;
    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            Toggler.EnrolComponents(Refs.Values);
            await JSRuntime.InvokeVoidAsync("createToggleButton");
        }
    }

    public void ToggleLinks()
    {
        Toggler.ToggleComponents();
    }
}

4.从 JavaScript 函数中调用实例方法
  上一个示例中的复杂性部分来自于对更新 Razor 组件对象的静态方法的响应。另一种方法是为 JavaScript 代码提供对实例方法的引用,然后可以直接调用该实例方法。第一步是将 JSInvokable 属性添加到JavaScript代码将要调用的方法中。
  下面 Services 文件夹的 ToggleService.cs 类定义的 ToggleComponents 方法应用属性。

[JSInvokable]
public bool ToggleComponents()
{
    enabled = !enabled;
    components.ForEach(c => c.SetEnabled(enabled));
    return enabled;
}

  下一步是为JavaScript 函数提供一个对象的引用,该对象的方法将被调用,在Blazor文件夹的 NavLayout.razor文件中提供实例。

protected async override Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        Toggler.EnrolComponents(Refs.Values);
        await JSRuntime.InvokeVoidAsync("createToggleButton",
            DotNetObjectReference.Create(Toggler));
    }
}

  DotNetObjectRefcrence.Create 方法创建对对象的引用,该引用使用 JSRuntime.InvokeVidAsync 方法作为参数传递给 JavaScript 函数。最后一步是用 JavaScript 接收对象引用,并在单击按钮元素时调用其方法,在wwwroot 文件夹的interop.js 文件中调用 C#方法。

function createToggleButton(toggleServiceRef) {
    let sibling = document.querySelector("button:last-of-type");
    let button = document.createElement("button");
    button.classList.add("btn", "btn-secondary", "btn-block");
    button.innerText = "JS Toggle";
    sibling.parentNode.insertBefore(button, sibling.nextSibling);
    button.onclick = () => toggleServiceRef.invokeMethodAsync("ToggleComponents");
}

  JavaScript 函数接收对 C#对象的引用作为参数,并使用 invokeMethodAsync 调用它的方法将方法的名称指定为参数。也可提供方法的参数,但在本例中不是必需的。重启 ASP.NET Core,请求 http://localhost:5000,然后单击 JS Toggle 按钮。组件中的更改是通过 ToggleService 对象管理的。

ASP.NET Core防伪令牌实战:从CSRF防御到Blazor SSR配置 跨站请求伪造(CSRF)是一种常见的Web安全威胁,攻击者利用用户已登录的会话,诱导其执行非预期的操作。其防御核心在于验证请求的合法性,确保操作来自可信来源。防伪令牌技术通过生成一次性随机令牌,结合会话凭证进行双重验证,有效阻断恶意请求。在ASP.NET Core中,该机制通过中间件和属性验证实现,为表单提交和状态修改操作提供基础防护。随着.NET版本更新,自动CSRF保护功能引入,基于浏览器安全头进行智能拦截,但防伪令牌仍是敏感操作的核心保障。在Blazor SSR场景中,最新版本要求显式启用中间件验证, 阅读详情

相关推荐

asp .net core blazor 是什么?

我想显从网页的显示历史变化来了解什么是asp .net core blazor 1、第一阶段:静态网页全部下载并显示阶段 在服务器端,程序员写好一个完整的.html网页。浏览一篇网页时,浏览器首先将整个网页下载下来,并显示出来。这个阶段有个很明显的缺点,当网页的部分内容变化比较频繁时,每次在浏览器和服务器之间都要传输一整个.html文件。而这个文件的大部分内容是重复的,只有少部分内容是不同的。...

freewzx2005的专栏 1409

.Net Core开发学习(四) ——Blazor(MVVM)应用

.Net Core开发学习(四) ——Blazor(MVVM)应用 MVVM(Model-View-ViewModel) MVVM,双向数据绑定。既 模型数据 与 页面显示的数据 双向绑定,改变视图数据 也会 改变模型数据。 使用Blazor框架可以减少很多Js脚本代码甚至可以无Js脚本实现快速开发。当然,想要做到这点,必须浏览器与服务器保持实时连接,所以Blazor的底层是基于WebSocket的。 现在比较出名的mvvm架构的框架有vue.js,angular.js等。 创建Blazor应用 创

自云—自在之心,无缚于体 4376

创建 ASP.NET Core 应用与 Blazor Server 入门指南

本文通过构建一个示例应用程序,深入介绍ASP.NET Core中的控制器和视图创建,以及如何使用Blazor Server为Web应用增加客户端交互性。文中详细说明了如何配置和运行ASP.NET Core项目,展示了控制器和Razor页面的使用,以及Blazor Server组件的创建和事件处理。

weixin_42509888的博客 959

全面的ASP.NET Core Blazor简介和快速入门

因为咱们的MongoDB入门到实战教程Web端准备使用Blazor来作为前端展示UI,本篇文章主要是介绍Blazor是一个怎样的Web UI框架,其优势和特点在哪?并带你快速入门上手ASP.NET Core Blazor(当然这个前提是你要有一定的C#编程基础的情况,假如你完全没有接触过C#的话建议你先从基本语法学起)。Blazor Server 应用程序在服务器上运行,可享受完整的 .NET Core 运行时支持。所有处理都在服务器上完成,UI/DOM 更改通过 SignalR 连接回传给客户端。

专注于C#/.NET/.NET Core学习、工作、面试干货和实战教程分享。这里聚焦了大量的C#/.NET/.NET Core优质文章、开源项目、实用工具和学习、工作、面试心得。 2526

深入理解「二进制掩码」:从原理到实践

二进制掩码本质上是一个二进制数,用于通过位操作(如与、或、非、异或等)选择性地操作目标数据的某些位。掩码的每一位(bit)可以看作一个“开关”,决定是否对目标数据的对应位进行操作。二进制掩码是位操作的灵魂,掌握它不仅能提升代码效率,还能解锁许多高级编程技巧。从基础的位提取到复杂的子集枚举,掩码的应用无处不在。希望本文的讲解和代码示例能帮助你快速上手,并在实际项目中灵活运用。如果你有更多关于掩码的疑问或应用场景,欢迎在评论区留言交流!

m0_73494933的博客 2432

在IIS上部署ASP.NET Core Web API和Blazor Wasm详细教程

前段时间我们完成了七天.NET 8 操作 SQLite 入门到实战的开发系列教程,有不少同学留言问如何将项目发布部署到IIS上面运行。本篇文章我们就一起来讲讲在IIS上部署ASP.NET Core Web API和Blazor Wasm。

专注于C#/.NET/.NET Core学习、工作、面试干货和实战教程分享。这里聚焦了大量的C#/.NET/.NET Core优质文章、开源项目、实用工具和学习、工作、面试心得。 3492

2.6 SST的核心性能指标体系

本文构建了固态变压器(SST)的核心性能指标体系,涵盖电气性能、可靠性、经济性和环境适配性四大类指标。电气性能指标包括运行效率(≥97%)、功率密度(≥900kVA/m³)、谐波畸变率(≤3%)等关键参数;可靠性指标设定MTBF≥43800h、年均故障率≤1.2次/年等标准;经济性指标对比分析了初始购置成本(45-55万元)和全生命周期成本(48-55万元);环境适配性指标则明确了温度、海拔等工况要求。该体系采用量化公式和国标限值,为SST的性能测试、选型和优化提供了统一标准。

技术工作者 596

.NET 10 中的 ASP.NET Core:Blazor、API 和 OpenAPI 的重大更新

微软发布.NET 10版本中ASP.NET Core的全面更新,涵盖Blazor、Minimal API等多个方面。Blazor获得最显著改进,包括安全示例更新、客户端指纹识别等功能。Minimal API新增验证支持和服务器发送事件功能。OpenAPI支持升级至3.1版本,提高文档生成质量。此外还优化了身份验证、异常处理及性能表现,并新增测试支持和JSON解析增强功能。

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 5931

第三篇:AMD 和 Intel

它像“乐高积木”一样,可以通过标准化的接口与其他部分组合,构建复杂系统。理解组件后,你会发现从操作系统到微服务,现代软件本质上都是组件的组合!

u013089100的博客 1030

抗性基因分析避坑指南:从数据库选择到结果解读的全流程经验分享

本文系统分享了抗性基因分析从数据库选择到结果解读的全流程避坑经验。针对宏基因组研究,重点剖析了SARG、BacMet等核心数据库的适用场景与组合策略,并提供了实验设计、序列比对阈值设定、丰度归一化及结果生物学解读的关键优化建议,旨在帮助研究者获得更可靠、深入的分析结果。

weixin_29233333的博客 200

ASP.NET Core 和 Blazor 更新

.NET Core 3.0 preview 8现在已经可用,它包含了对 ASP.NET Core 和 Blazor 的一系列新更新。更新内容如下: 项目模板更新 清理 Visual Studio 中的顶级模板 Visual Studio 中“Create a new project”对话框中的顶级 ASP.NET Core 项目模板不再出现在“Create a new ASP.NET Cor...

寒冰屋的专栏 2237

基于Coze平台从零构建AI智能体:以测试用例生成为例的实战指南

在人工智能技术快速发展的今天,大语言模型(LLM)和提示词工程(Prompt Engineering)已成为构建智能应用的核心技术。其原理在于通过自然语言指令引导模型完成特定任务,其技术价值在于极大地降低了AI应用开发的门槛,使非专业开发者也能快速实现想法。这一技术广泛应用于自动化办公、智能客服、内容生成等场景。本文聚焦于字节跳动旗下的Coze平台,该平台通过可视化工作流编排和预置技能,将上述技术封装为易用的工具。文章以“根据产品需求文档(PRD)自动生成测试用例”这一具体场景为例,详细拆解了从需求分析、工

weixin_30617695的博客 337

[.NET学习笔记] - 在ASP.NET Core MVC中使用Blazor组件

场景 .NET5发布了,突然对Blazor有了点兴趣,想尝尝鲜。 Blazor有两种模式,server-side与client-side(WASM)。这里打算在已有的MVC项目中使用Blazor组件,所以用的server-side。 use blazor component in ASP.NET Core 3.1 MVC。 解决方案 step1 startup.cs配置。 // ConfigureServices services.AddServerSideBlazor(); services.AddAnt

kyw的专栏 2169

别再问ARM麒麟怎么装微信了!手把手教你用铠大师搞定Windows软件(飞腾/海思芯片实测)

本文详细介绍了如何在ARM架构的信创电脑(如飞腾/海思芯片)上使用铠大师安装和运行Windows软件,解决微信、Office等常用软件的兼容性问题。通过实测数据对比,铠大师在性能和易用性上显著优于传统方案,为麒麟系统用户提供了一套完整的解决方案。

weixin_28736355的博客 889

2025年数学建模国赛高教社杯A题、B题、C题、D题、E题详细思路和代码 模型||插值与拟合

核心思想:构造一个精确通过所有已知离散数据点(xi, yi)的函数y = f(x),并以此函数来估算或预测未知点的值。基本假设:我们认为已知的数据点是100%精确、无误差的(或者误差可忽略不计),比如理论计算值、高精度仪器测量值等。我们的目标是“还原”或“重建”出点与点之间的真实函数关系。关键特征精确性:曲线或曲面必须穿过每一个样本点。局部性:插值结果严重依赖于局部数据点的分布和数值。用途:用于“补全”数据、填充缺失值、进行函数近似等。常见方法多项式插值:拉格朗日插值、牛顿插值。

2201_76125261的博客 802

ASP.NET Core Blazor 2:使用 Blazor Server (1)

  Blazor 是 ASP.NET Core 新添加的一个功能,它向 Web 应用程序添加客户端交互性。Blazor 有两个变种,本章将重点介绍 Blazor Server,另一种是 Blazor WebAssembly。解释它解决的问题和它是如何工作的。展示如何配置 ASP.NET Core应用程序来使用 Blazor Server,并描述使用 Razor 组件时可用的基本特性,这是 Bla...

噢~ 1474

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Asp.Net Core 10.0 中的 Blazor 增强功能

ASP.NET Core 10.0为Blazor带来重大升级,显著提升其作为全栈开发框架的竞争力。关键改进包括:更快的启动速度(通过静态资源指纹识别和预压缩优化);持久化组件状态功能,解决页面刷新后状态丢失问题;增强的混合应用集成与验证功能;QuickGrid组件升级支持条件样式和虚拟化;新增密码支持和SSE流式通信能力。这些改进使Blazor在性能、开发效率和安全性方面达到企业级标准,为构建跨平台应用提供了更强大的.NET统一解决方案。

csdn_aspnet的专栏,请点击博客主页右上角三个点中的私信联系 6250

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

使用Canvas扩展绘制动态ASP.NET Core Blazor气泡图

下载源234.8 KB 介绍 在今天的文章中,我们将看到如何使用HTML5 Canvas和ASP.NET Core Blazor Web应用程序绘制自己的气泡图。 背景 Visual Studio 2019 16.3或更高版本 .NET Core 3.0 SDK 使用代码 步骤1:创建ASP.NET Core Blazor服务器应用程序 安装上面列出的所有必备组件后,单击桌...

寒冰屋的专栏 3179

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

使用Canvas扩展绘制动态ASP.NET Core Blazor条形图

目录 介绍 背景 使用代码 步骤1:创建ASP.NET Core Blazor服务器应用程序 运行测试应用程序 步骤2:安装软件包 步骤3:建立模型类别 创建服务类 步骤4:将服务添加到Startup.cs 步骤5:使用客户项目 添加Razor组件 Import部分 HTML设计和数据绑定部分 函数(Function)部分 导航菜单 生成并运行应用程序 兴趣点 ...

寒冰屋的专栏 2575

.NET开发技术推荐,如何使用ASP.NET Core和Blazor进行开发

当使用.NET开发MES(制造执行系统)时,前端和后端的开发方式可以根据项目需求、团队技能和项目规模进行选择。以下是一些常见的开发方式建议::ASP.NET Core 是一个跨平台的、高性能的、开源的 Web 框架,非常适合构建现代、可扩展的 Web 应用程序。它支持多种开发模式,包括 MVC(模型-视图-控制器)和 Web API,可以轻松地与数据库和其他服务进行交互。ASP.NET Core 还具有强大的依赖注入和中间件支持,使得应用程序的可扩展性和可维护性更高。

slty_123的博客 918

ASP.NET Core 10中的Blazor WebAssembly性能优化实践

ASP.NET Core 10为Blazor WebAssembly的性能优化提供了有力的工具和方法。通过合理运用代码压缩、懒加载和运行时优化等技术,可以显著提升Blazor WebAssembly应用的性能,为用户带来更好的体验。#标签:#ASP.NET Core 10 #Blazor WebAssembly #性能优化 #懒加载 #代码压缩Blazor WebAssembly作为一种将.NET应用带到浏览器端的技术,在近年来得到了广泛的关注和应用。然而,随着应用规模的增大,性能问题逐渐凸显。

dotnethello的博客 8550

使用Entity Framework和Web API的ASP.NET Core Blazor CRUD

目录 介绍 背景 先决条件 使用代码 第1步——创建数据库和表 第2步——创建ASP.NET Core Blazor应用程序 ASP.NET Core Blazor解决方案的新增功能是什么? 客户端项目 服务端项目 共享项目 运行以测试应用程序 使用实体框架 安装包 为CRUD操作创建Web API 使用客户端项目 添加Razor视图 导入部分 HTML设计和数...

寒冰屋的专栏 2526

ASP.NET Core Blazor托管模型详解:交互式服务端与WebAssembly如何抉择

**ASP.NET Core Blazor 托管模型**决定了你的 C# 组件代码究竟运行在哪里:是在服务器上以**交互式服务端(Interactive Server)**模式运行,还是在浏览器中基于 **Blazor WebAssembly** 客户端运行,亦或是通过 **Blazor Hybrid** 嵌入原生桌面/移动应用。本文面向新手,用最少的代码带你理解三种托管模型的工作原理、优劣势,并

gitblog_00760的博客 935

ASP.NET Core Blazor Wasm发布部署IIS详细教程

安装 .NET Core 托管捆绑包(Hosting Bundle)在将 .NET Core 应用程序部署到 IIS 时是一个必要的步骤。Internet Information Services (IIS) 是一种灵活、安全且可管理的 Web 服务器,用于托管 Web 应用(包括 ASP.NET Core)。URL 重写模块下载页:https://www.iis.net/downloads/microsoft/url-rewrite#additionalDownloads。

专注于C#/.NET/.NET Core学习、工作、面试干货和实战教程分享。这里聚焦了大量的C#/.NET/.NET Core优质文章、开源项目、实用工具和学习、工作、面试心得。 1844
上一篇: ASP.NET Core Blazor 3:使用 Blazor Server (2)
下一篇: ASP.NET Core Blazor 5:Blazor表单和数据
似水明俊德
博客等级 码龄8年 247粉丝 276原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值