Location>code7788 >text

NET8 Blazor from Start to Finish: (II) Components

Popularity:116 ℃/2024-08-16 15:25:16

catalogs
  • Blazor Components
    • infrastructural
    • Routing
    • parameters
      • Component parameters
      • routing parameter
    • life cycle event
    • Status Changes
    • Component Events

Blazor Components

infrastructural

Create a new project named MyComponents, select Auto for the interaction type of the project template, and leave the other options as default:
image

client component (Auto/WebAssembly):
There will be two items inside the final solution:Server-side projectsClient projects, components can be categorized into the following two types of components according to the storage items:

  • server-side component:

    • Primarily for server-side rendering (SSR)
    • Being placed in a server-side project
    • For scenarios that do not require real-time interaction or complex user interaction
  • client component (Auto/WebAssembly):

    • Components are located within the client project
    • Compiled using WebAssembly technology and able to interact directly with the browser
    • Ideal for application scenarios that require interactivity and real-time updates
    • Using SignalR enables real-time communication to enhance the functionality of your components.

The two component selection principles are as follows.

  • If the component doesn't require interactivity, use it as theserver-side renderingThe components of the
  • If the component requires interactivity (e.g., responding to user input, real-time data updates, etc.), it should be considered as theclient componentThe SignalR provides real-time communication capabilities that can be utilized in a variety of ways.

Create a new Demo component in the client project:

<!-- option Auto maybe WebAssembly ,Otherwise, no interaction is possible -->
@rendermode InteractiveAuto

<h3>Demo</h3>

<!-- Show labels only when text is not empty -->
@if (textInfo is not null)
{
    <h4>Info: @textInfo</h4>
}

<!-- Button Style Reference Counter subassemblies -->
<button class="btn btn-primary" @onclick="UpdateText">Update Text</button>
<!-- Invoking methods by delegation,You can pass in the parameter -->
<button class="btn btn-primary" @onclick="(()=>{UpdateNumber(10);})">Update Number</button>


@code {
    private string? textInfo = null;

    private void UpdateText()
    {
        textInfo = "This is the new information";
    }

    private void UpdateNumber(int i = 0)
    {
        textInfo = $"This is number {i}";
    }
}

Reference the Demo component in the Home page of the server-side project:

@page "/"

<PageTitle>Home</PageTitle>

<h1>Hello, world!</h1>

Welcome to your new app.

<Demo />

Reference the namespace of the Demo component in _Imports.razor:

@using 

Routing

Add a Start component to the client project with the following razor code:

@*Components can have multiple routes at the same time *@
@page "/page"
@page "/pages/start"

@*Component names can be used as routes**@
@attribute [Route(nameof(Start))]

@*Page jumps must specify interactivity and inject a navigation manager *@
@rendermode InteractiveAuto
@inject NavigationManager Navigation

<h3> Start</h3>

@*Jump to Counter component via method *@
<button class="btn btn-primary" onclick="@(()=>(nameof(Counter)))">Go to Counter</button>

@* Perform a full page reload *@
<button class="btn btn-primary" onclick="@(()=>(true))">Refresh</button>
@code {

}

The code above demonstrates how to make a page jump using a route and navigation manager.Components can have multiple routes at the same time, or you can use the component name as a route
Used when jumping to other componentsEnhanced NavigationreferenceEnhanced navigation and form handling

parameters

Component parameters

Add a BetterCounter component to the client project with the following razor code:

@rendermode InteractiveAuto

<h3>BetterCounter</h3>
<p role="status">Current count: @CurrentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {

    //Representation of target members as component parameters
    [Parameter]
    public int CurrentCount { get; set; }

    private void IncrementCount()
    {
        CurrentCount++;
    }
}

Component parameters pass data to the component, and are defined using public C# properties in the component class that contain the [Parameter] featurereferenceComponent parameters cap (a poem)one-way binding

When using a component, you need to pass the target member as a component parameter to the component, such as referencing the BetterCounter component on the Home page:

<BetterCounter CurrentCount="100" />
<!-- maybe -->
<BetterCounter CurrentCount=@currentCount />

routing parameter

The router uses routing parametersFill the corresponding component parameter with the same name, the route parameter name is not case-sensitiveReference Documentationrouting parameter

Add the following route to the razor code of the BetterCounter component:

@*Routing Parameters (Unconstrained) *@
@page "/BetterCounter/{CurrentCount}"

@*Routing parameter constraints *@
@page "/BetterCounter/{CurrentCount:int}"

@*Optional Route Parameters (use with any of the above routes to achieve optional effects)*@
@page "/BetterCounter"

In order to implement optional routing parameters, a default value needs to be added to the component:

// Represent the target member as a component parameter
// Need to change the type of the parameter attribute to nullable so you can tell if it's been assigned a value or not
[Parameter]
public int? CurrentCount { get; set; }

//Specify default values for optional parameters
protected override void OnInitialized()
{
    (); }//Specify the default value for the optional parameter.
    CurrentCount = CurrentCount ? 1; }
}

Add a Titlet member to accept query string arguments:


// Specify that the component parameters come from the query string
//Route:/BetterCounter?Titlet=asd
[SupplyParameterFromQuery]
public string? Titlet { get; set; } = "BetterCounter".
  • routing parameter: In the add component's@page declaration by enclosing the names of the routing parameters in a pair of{ curly brackets } In the example, the routing parameters are defined in the URL, refer to the samplerouting parameter

  • Routing Parameter Constraints: suffixed by a colon, followed by the constraint type, constraint type reference documentationrouting constraint
    routing (computing)/BetterCounter/abs As an example:

    • Type conversion exceptions are reported when there are no routing constraints (strings cannot be converted to int types)
    • A 404 error is displayed when there is a route constraint (no match for the URL)
  • Optional Routing Parameters:BlazorOptional routing parameters are not explicitly supported, but by adding multiple@page Statement that equivalent routing parameters can be easily implemented, refer to the articleOptional Routing Parameters

  • query string: Use[SupplyParameterFromQuery] attribute specifies that the component parameter comes from a query string, see the documentation for more application scenarios.query string

life cycle event

The following simplified diagram shows the Razor component lifecycle event handling, referring to the documentationlife cycle event

image

Add logging to the Counter component to observe the component's lifecycle:

@inject ILogger<Counter> log

//...

@code {
    //...
    protected override void OnInitialized()
    {
        ($"Initialized at {}");
    }
    protected override void OnParametersSet()
    {
        ($"ParametersSet at {}");
    }
    protected override void OnAfterRender(bool firstRender)
    {
        ("OnAfterRender: firstRender = {FirstRender}", firstRender);
    }
}
  • Component Initialization (OnInitialized{Async}) : Specialized for initializing components throughout the life cycle of a component instance, parameter values and parameter value changes should not affect the initialization performed in these methods.

  • After setting the parameters (OnParametersSet{Async}): Called after initializing the component in OnInitialized or OnInitializedAsync or when the parent component is re-presented with changed parameters.

  • After component rendering (OnAfterRender{Async}): The OnAfterRender and OnAfterRenderAsync components are rendered interactively and called after the UI has been updated (e.g., after an element has been added to the browser's DOM).firstRender Parameters:

    • Set to true the first time a component instance is rendered.
    • can be used to ensure that the initialization operation is performed only once.

After running and navigating to the Counter screen, the console output is as follows:
image

Status Changes

StateHasChanged Notifies the component that its status has changed. If applicable.Calling StateHasChanged causes the component to be re-rendered.

StateHasChanged will be called automatically for the EventCallback method, or you can call StateHasChanged manually in the component as needed:

private async void IncrementCount()
{
    currentCount++;
    await (1000);
    StateHasChanged();

    currentCount++;
    await (1000);
    StateHasChanged();

    currentCount++;
    await (1000);
    StateHasChanged();
}

If you don't call StateHasChanged, only the first and the last value will show 1 when you click on it, but if you use StateHasChanged, it will show 1, 2 and 3 in turn.

Component Events

A common scheme for nesting components isExecute a method in the parent component when a child component event occurs(e.g., the onclick event in a subcomponent), and to expose events across components, use theEventCallback The parent component can assign callback methods to the child component's EventCallback.

Add an event to the Counter component:

@code {
    private int currentCount = 0;

    //Define an event callback parameter
    [Parameter]
    public EventCallback<int> OnCounterChange { get; set; }

    private async Task IncrementCount()
    {
        currentCount++;
        //trigger event callback
        await (currentCount);
    }
}

Assign callback methods to the Counter component's events in another client-side component (the server-side component will report an error):

<Counter OnCounterChange="UpdateCounter" />

@code {
    private int currentCount = 0;
    private void UpdateCounter(int val)
    {
        currentCount = val;
    }
}