中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

ASP.NET Core Blazor 核(he)心功能一:Blazor依賴注(zhu)入與狀態管理指南

大家好,我是碼農剛子本(ben)文詳細介(jie)紹了(le)Blazor框(kuang)架中(zhong)的(de)(de)(de)依賴(lai)注入機(ji)制和狀(zhuang)態(tai)管理(li)方(fang)(fang)案(an)。依賴(lai)注入部分闡(chan)述了(le)服務注冊的(de)(de)(de)三種(zhong)(zhong)生命周期方(fang)(fang)式(shi)(Singleton/Scoped/Transient)及在組(zu)(zu)件(jian)(jian)中(zhong)的(de)(de)(de)使(shi)用方(fang)(fang)法。狀(zhuang)態(tai)管理(li)章節(jie)系統梳理(li)了(le)7種(zhong)(zhong)解(jie)決(jue)方(fang)(fang)案(an):從簡單的(de)(de)(de)組(zu)(zu)件(jian)(jian)內(nei)狀(zhuang)態(tai)到(dao)父(fu)子組(zu)(zu)件(jian)(jian)通(tong)信、級聯參(can)數,再到(dao)全局狀(zhuang)態(tai)容器和Flux/Redux模式(shi),并提供了(le)本(ben)地存(cun)儲持久化方(fang)(fang)案(an)。文章還介(jie)紹了(le)@ref指(zhi)令的(de)(de)(de)使(shi)用場景,包括組(zu)(zu)件(jian)(jian)引用、元素操作(zuo)和循環處(chu)理(li)等(deng)。最后給(gei)出了(le)不同場景下的(de)(de)(de)狀(zhuang)態(tai)管理(li)選擇建議,幫助開發者構建更健壯。

一(yi)、依賴(lai)注(zhu)入基礎

Blazor 提供了強大的依賴注入(Dependency Injection, DI)功能,用于將服務以解耦的方式注入到組件中,它幫(bang)助我們實現松耦合的代碼(ma)設計,提高可測試性(xing)和可維護性(xing)。

什么是依賴(lai)注入?

依賴(lai)注入是一種設計模式,它允(yun)許類從外部接(jie)收(shou)其依賴(lai)項,而不是自己創(chuang)建(jian)它們(men)。在 Blazor 中(zhong),這(zhe)意(yi)味著組件不需要知道如何(he)創(chuang)建(jian)服(fu)務(wu),而是通(tong)過構造函數或屬性接(jie)收(shou)這(zhe)些服(fu)務(wu)。

二、注冊(ce)和使用服務

1、創建自定義(yi)服務

1. 定義服務(wu)接口

public interface ICounterService
{
    int Increment(int currentValue);
    int Decrement(int currentValue);
    void Reset();
}

2. 實現服務

public class CounterService : ICounterService
{
    public int Increment(int currentValue)
    {
        return currentValue + 1;
    }
    
    public int Decrement(int currentValue)
    {
        return currentValue - 1;
    }
    
    public void Reset()
    {
        // 重(zhong)置邏輯
    }
}

2、注冊服(fu)務

在 Program.cs 文件中配置服(fu)務(wu)容器:

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");

// 注冊服(fu)務(wu)
builder.Services.AddSingleton<ICounterService, CounterService>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddTransient<IEmailService, EmailService>();

// 注冊內置服務
builder.Services.AddLocalStorage();
builder.Services.AddAuthorizationCore();

await builder.Build().RunAsync();

3、服務生命周期

Blazor 支持三(san)種服務生命周期(qi):

  • Singleton:整個應用(yong)生(sheng)命周(zhou)期(qi)內只有一個實例
  • Scoped:每個用戶會話有(you)一(yi)個實(shi)例(Blazor Server)或每個瀏覽器標簽頁(Blazor WebAssembly)
  • Transient:每次請求時(shi)創建新(xin)實(shi)例

4、在組件中(zhong)使用(yong)依賴(lai)注入

1. 使用 [Inject] 特性

@page "/counter"
@inject ICounterService CounterService
 
<h3>Counter</h3>
<p>Current count: @currentCount</p>
 
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
 
@code {
    private int currentCount = 0;
    
    private void IncrementCount()
    {
        currentCount = CounterService.Increment(currentCount);
    }
}

2. 在代碼中使用(yong)注入的服務

@page "/user-profile"
@inject IUserService UserService
@inject NavigationManager Navigation

<h3>User Profile</h3>

@if (user != null)
{
    <div>
        <p>Name: @user.Name</p>
        <p>Email: @user.Email</p>
    </div>
}

@code {
    private User user;
    
    protected override async Task OnInitializedAsync()
    {
        user = await UserService.GetCurrentUserAsync();
    }
    
    private async Task UpdateProfile()
    {
        await UserService.UpdateUserAsync(user);
        Navigation.NavigateTo("/success");
    }
}

5、高級依(yi)賴注入(ru)用法

1. 工(gong)廠模式(shi)注冊(ce)

builder.Services.AddSingleton<ICounterService>(provider =>
{
    // 復雜的創建邏(luo)輯(ji)
    return new CounterService();
});

2. 選項模(mo)式

// 配置(zhi)選項類
public class ApiOptions
{
    public string BaseUrl { get; set; }
    public int TimeoutSeconds { get; set; }
}

// 注冊選項
builder.Services.Configure<ApiOptions>(options =>
{
    options.BaseUrl = "//api.example.com";
    options.TimeoutSeconds = 30;
});

// 在服務中(zhong)使用
public class ApiService
{
    private readonly ApiOptions _options;
    
    public ApiService(IOptions<ApiOptions> options)
    {
        _options = options.Value;
    }
}

3. 條件注冊

#if DEBUG
builder.Services.AddSingleton<ILogger, DebugLogger>();
#else
builder.Services.AddSingleton<ILogger, ProductionLogger>();
#endif

三、組(zu)件狀態管理

在Blazor開發中,狀(zhuang)態管(guan)理是(shi)(shi)構建交(jiao)互式Web應用的(de)(de)核心挑戰。無論是(shi)(shi)簡單的(de)(de)計數器組件(jian)還是(shi)(shi)復雜的(de)(de)實時協作系(xi)統,選擇(ze)合適的(de)(de)狀(zhuang)態管(guan)理方案直接影響(xiang)應用性(xing)能和可維(wei)護性(xing)。

1、理解Blazor中的狀(zhuang)態管理

  • 狀(zhuang)(zhuang)態是(shi)指應用程序或組件(jian)在(zai)某一(yi)(yi)時刻的(de)(de)數據(ju)或信(xin)息。例(li)如,一(yi)(yi)個(ge)(ge)(ge)(ge)計數器組件(jian)可(ke)以(yi)(yi)有(you)一(yi)(yi)個(ge)(ge)(ge)(ge)表示當前計數值的(de)(de)狀(zhuang)(zhuang)態,一(yi)(yi)個(ge)(ge)(ge)(ge)表單組件(jian)可(ke)以(yi)(yi)有(you)一(yi)(yi)個(ge)(ge)(ge)(ge)表示用戶(hu)輸入的(de)(de)狀(zhuang)(zhuang)態,一(yi)(yi)個(ge)(ge)(ge)(ge)購物車組件(jian)可(ke)以(yi)(yi)有(you)一(yi)(yi)個(ge)(ge)(ge)(ge)表示選中(zhong)商品的(de)(de)狀(zhuang)(zhuang)態等。狀(zhuang)(zhuang)態管(guan)理是(shi)指如何存(cun)儲、更新、獲取和傳遞這些數據(ju)或信(xin)息。
  • 在(zai)Blazor中,每個(ge)組件都有自己(ji)的私有狀(zhuang)態,它只(zhi)能被該組件訪(fang)問和修(xiu)改。如果要將狀(zhuang)態從一(yi)(yi)個(ge)組件傳(chuan)遞(di)給另一(yi)(yi)個(ge)組件,或(huo)者在(zai)多(duo)個(ge)組件之間共享狀(zhuang)態,就(jiu)需要使(shi)用一(yi)(yi)些技(ji)術或(huo)模式來實現(xian)。下面我們將介紹一(yi)(yi)些常(chang)見的方法。

2、組件內狀態:最簡單的狀態管理

Blazor組件最基礎的(de)狀態(tai)(tai)管理方式是使用(yong)組件內部的(de)字段或屬性保存(cun)狀態(tai)(tai)。這種模式適用(yong)于狀態(tai)(tai)僅在(zai)單個(ge)組件內部使用(yong)且無需共享的(de)場景,如計數器、表單輸入等基礎交互。

@page "/counter"

<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    private int currentCount = 0;

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

上述代碼展示了典型的組件內狀態模式,currentCount字段存儲計數器狀態,IncrementCount方法修改狀態(tai)并(bing)自動觸發UI重新渲染。這(zhe)種模式的優勢在于實現簡(jian)單、零(ling)外部依賴,適合快速開發獨立功能組件。

3、父子組件通(tong)信:參數和事件回(hui)調

如果要將父組件的狀態傳遞給子組件,或者從子組件獲取更新后的狀態,可以使用參數屬性(xing)來(lai)實現。

參數是指父組件向子組件傳遞數據或信息的方式。參數可以是任意類型的值,例如字符串、數字、布爾值、對象、委托等。要定義一個參數,需要在子組件中使用[Parameter]特性來標記一個公共屬性,并且該屬性的類型必須與父組件傳遞的值相同。例如:

這樣就定義了一個名為Counter的參數,在子組件中可以使用以下語法來獲取它的值:

<p>The counter value is @Counter</p>

在父(fu)組件中(zhong),可以使用以下(xia)語(yu)法來(lai)為參數賦值(zhi):

<CounterComponent Counter="@currentCount" />

@code {
    private int currentCount = 0;
}

這(zhe)樣就將父組件中的(de)變量(liang)currentCount作為參數值(zhi)傳遞給了子(zi)組件。如(ru)果要實現從父到子(zi)單(dan)向(xiang)綁定(ding)。

屬(shu)性(xing)是(shi)指子(zi)組件(jian)向父組件(jian)傳遞數據(ju)或信息(xi)的方式。屬(shu)性(xing)可以是(shi)任意類型(xing)的值(zhi),但(dan)通常是(shi)一個事件(jian)回調(EventCallback)或一個動作(Action),用(yong)于在(zai)子(zi)組件(jian)中(zhong)觸(chu)發父組件(jian)定義(yi)的一個方法,從而將數據(ju)或信息(xi)傳遞給父組件(jian)。要(yao)(yao)定義(yi)一個屬(shu)性(xing),需要(yao)(yao)在(zai)子(zi)組件(jian)中(zhong)使(shi)用(yong)[Parameter]特性(xing)來標(biao)記(ji)一個公共屬(shu)性(xing),并且(qie)該(gai)屬(shu)性(xing)的類型(xing)必須是(shi)EventCallback<T>或Action<T>,其(qi)中(zhong)T是(shi)要(yao)(yao)傳遞的數據(ju)或信息(xi)的類型(xing)。例如:

<h3>CounterComponent</h3>
<p>The counter value is @Counter</p>
<button @onclick="CounterChangedFromChild">Update Counter from Child</button>
@code {
    [Parameter]
    public int Counter { get; set; }
 
    [Parameter]
    public EventCallback<int> OnCounterChanged { get; set; }
 
    private async Task CounterChangedFromChild()
    {
        Counter++;
        await OnCounterChanged.InvokeAsync(Counter);    
    }
 
}

以上例子中就定義了一個名為OnCounterChanged的屬性,將子組件中的變量Counter作(zuo)為參數傳遞給了父組件。在父組件中,可以使(shi)用以下(xia)語法來為屬(shu)性賦值:

<CounterComponent OnCounterChanged="HandleCounterChanged" />

這樣就(jiu)將父組(zu)件(jian)中定義的一個方法名作為(wei)屬性(xing)值(zhi)傳(chuan)遞(di)給了子(zi)組(zu)件(jian)。該方法必須接(jie)受(shou)一個與屬性(xing)類型(xing)相(xiang)同的參(can)數(shu),并且可(ke)以(yi)在(zai)其中處(chu)理數(shu)據或信息。例如:

@code{
    private void HandleCounterChanged(int counter)
    {
        Console.WriteLine($"The counter value is {counter}");
    }
}

這樣(yang)就實(shi)現(xian)了(le)從子到父單向傳遞(di)數(shu)據或信(xin)息,并且可以在任(ren)何時候觸發。

使用組件參(can)(can)數(shu)和屬性(xing)傳遞狀態:適合父子(zi)組件之間(jian)的簡單狀態傳遞,可以使用[Parameter]或者(zhe)級聯參(can)(can)數(shu)[CascadingParameter]特性(xing)來標記組件參(can)(can)數(shu),并且(qie)使用<Component Parameter="Value" />或者(zhe)<CascadingValue Value="Value"><Component /></CascadingValue>語法來傳遞狀態。

4、級聯參數和值

<!-- AppStateProvider.razor -->
<CascadingValue Value="this">
    @ChildContent
</CascadingValue>
 
@code {
    [Parameter]
    public RenderFragment? ChildContent { get; set; }
 
    private string theme = "light";
    public string Theme
    {
        get => theme;
        set
        {
            if (theme != value)
            {
                theme = value;
                StateHasChanged();
            }
        }
    }
 
    public event Action? OnThemeChanged;
 
    public void ToggleTheme()
    {
        Theme = Theme == "light" ? "dark" : "light";
        OnThemeChanged?.Invoke();
    }
}
<!-- ConsumerComponent.razor -->
<div class="@($"app-{appState.Theme}")">
    <h3>當前主題: @appState.Theme</h3>
    <button @onclick="appState.ToggleTheme">切換主題</button>
</div>
 
@code {
    [CascadingParameter]
    public AppStateProvider appState { get; set; } = default!;
 
    protected override void OnInitialized()
    {
        if (appState != null)
        {
            appState.OnThemeChanged += StateHasChanged;
        }
    }
 
    public void Dispose()
    {
        if (appState != null)
        {
            appState.OnThemeChanged -= StateHasChanged;
        }
    }
}

5、狀態容器模式(全局狀態)

創建狀態容器服務

// Services/AppState.cs
public class AppState
{
    private int _counter;
    private string _userName = string.Empty;
 
    public int Counter
    {
        get => _counter;
        set
        {
            _counter = value;
            OnCounterChanged?.Invoke();
        }
    }
 
    public string UserName
    {
        get => _userName;
        set
        {
            _userName = value;
            OnUserNameChanged?.Invoke();
        }
    }
 
    public event Action? OnCounterChanged;
    public event Action? OnUserNameChanged;
 
    public void IncrementCounter()
    {
        Counter++;
    }
}

注冊服務

// Program.cs
builder.Services.AddScoped<AppState>();

在組件中使用

@inject AppState AppState
@implements IDisposable
 
<h3>計數器: @AppState.Counter</h3>
<h4>用戶: @AppState.UserName</h4>
 
<button @onclick="AppState.IncrementCounter">增加計數</button>
<input @bind="localUserName" @bind:event="onchange" placeholder="輸入用戶名(ming)" />
 
@code {
    private string localUserName
    {
        get => AppState.UserName;
        set
        {
            AppState.UserName = value;
            // 可(ke)以在(zai)這里添加其他邏(luo)輯
        }
    }
 
    protected override void OnInitialized()
    {
        AppState.OnCounterChanged += StateHasChanged;
        AppState.OnUserNameChanged += StateHasChanged;
    }
 
    public void Dispose()
    {
        AppState.OnCounterChanged -= StateHasChanged;
        AppState.OnUserNameChanged -= StateHasChanged;
    }
}

6、Flux/Redux 模式

什么是Flux模式?

Flux是一種應用(yong)程序架構模式(shi),專門(men)用(yong)于管(guan)理前端(duan)應用(yong)中的狀(zhuang)態(tai)。與(yu)常見的MVC模式(shi)不(bu)同(tong),Flux采用(yong)單向數據流的設計,使(shi)得狀(zhuang)態(tai)變化(hua)更加(jia)可預(yu)測和易于追蹤。

Flux模(mo)式(shi)的核心思想是(shi)將狀態管理與UI渲染分離,通過(guo)嚴格的規則來(lai)規范(fan)狀態變更的過(guo)程。這種模(mo)式(shi)最初由Facebook提出,后來(lai)被Redux等(deng)庫實現(xian),而Fluxor則是(shi)專門為(wei)Blazor應(ying)用設計的實現(xian)方(fang)案。

Flux模式的核心原則

  1. 狀態只讀原則

應用的狀(zhuang)態(tai)在任(ren)何情(qing)況下都不(bu)應該被直接修(xiu)改,這保證了(le)狀(zhuang)態(tai)變更的可控性。

  1. 動作驅動變更

任何(he)狀態變更都必須(xu)通過派發(dispatch)一個動作(action)來觸發。動作是一個簡(jian)單的對象(xiang),描述了發生了什么變化。

  1. 純函數處理

使用稱為"reducer"的純函數(shu)來(lai)處理動作,根據(ju)當前(qian)狀(zhuang)態(tai)和(he)動作生成新狀(zhuang)態(tai)。Reducer不會(hui)修改原(yuan)有狀(zhuang)態(tai),而是(shi)返回全(quan)新的狀(zhuang)態(tai)對象。

  1. 單向數據流

UI組件(jian)訂閱狀(zhuang)(zhuang)態變(bian)化,當狀(zhuang)(zhuang)態更(geng)新時自動(dong)(dong)重新渲染(ran)。用戶交互則通過派發(fa)動(dong)(dong)作來觸發(fa)狀(zhuang)(zhuang)態變(bian)更(geng),形成完整的單向(xiang)循環。

核心概念

  • ?狀態(State)?:定義應用數據模型,不(bu)可直接修改,需通過動作(zuo)(Action)觸(chu)發更新。
  • ?動作(Action)?:描述狀態(tai)變(bian)更意圖的對(dui)象,包含類型標識和有效載荷。
  • ?歸約器(Reducer)?:純函數,根(gen)據當前狀(zhuang)態(tai)和動(dong)作生(sheng)成新狀(zhuang)態(tai)。
  • ?效果(Effect)?:處理副作(zuo)用操作(zuo)(如 API 調用),監聽動作(zuo)并執(zhi)行異步任務。
  • 中間件(Middleware)中間(jian)件可以在動作(zuo)被派(pai)發到reducer之前或之后執行自定義(yi)邏(luo)輯,用于日志記錄、性能監控等橫切(qie)關注點。

使用 Fluxor 庫

首先安裝 Fluxor:

Install-Package Fluxor.Blazor.Web

定義狀態和動作

// Store/CounterState.cs
public record CounterState
{
    public int Count { get; init; }
}
 
// Store/Actions/IncrementCounterAction.cs
public record IncrementCounterAction;
 
// Store/Reducers/CounterReducers.cs
public static class CounterReducers
{
    [ReducerMethod]
    public static CounterState OnIncrementCounter(CounterState state, IncrementCounterAction action)
    {
        return state with { Count = state.Count + 1 };
    }
}

在組件中使用

@using Fluxor
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
 
<h3>計數器: @State.Value.Count</h3>
<button @onclick="Increment">增加</button>
 
@code {
    [Inject]
    private IState<CounterState> State { get; set; } = null!;
 
    [Inject]
    private IDispatcher Dispatcher { get; set; } = null!;
 
    private void Increment()
    {
        Dispatcher.Dispatch(new IncrementCounterAction());
    }
}

7、本地存儲持久化

使用 Blazor 本地存儲

@page "/counter2"
@inject IJSRuntime JSRuntime
 
<h3>持久化計數器: @count</h3>
<button @onclick="Increment">增加并保存</button>
 
@code {
    private int count = 0;
    private bool isInitialized = false;
 
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            await LoadFromStorage();
            isInitialized = true;
            StateHasChanged(); // 確(que)保在加載后更新UI
        }
    }
 
    private async Task Increment()
    {
        count++;
        await SaveToStorage();
        //StateHasChanged();
    }
 
    private async Task SaveToStorage()
    {
        if (isInitialized)
        {
            await JSRuntime.InvokeVoidAsync("localStorage.setItem", "counter", count);
        }
    }
 
    private async Task LoadFromStorage()
    {
        try
        {
            var savedCount = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "counter");
            if (int.TryParse(savedCount, out int result))
            {
                count = result;
            }
        }
        catch (Exception ex)
        {
            // 處理預(yu)渲(xuan)染期間的 JS 互操作錯(cuo)誤
            Console.WriteLine($"加載存儲時出錯: {ex.Message}");
        }
    }
 
}

8、狀態管理選擇指南

image

四、使用 @ref 引用組件

在 Blazor 中,@ref 指令用于(yu)獲取對組件(jian)或 HTML 元素的引用,讓你能夠(gou)在代碼中(zhong)直接(jie)操作它們。以下(xia)是詳細的使用方法(fa):

1、引用組件

基本用法

<!-- MyComponent.razor -->
<h3>計數器: @count</h3>
<button @onclick="Increment">增加</button>
 
@code {
    private int count = 0;
 
    public void Increment()
    {
        count++;
        StateHasChanged();
    }
 
    public void Reset()
    {
        count = 0;
        StateHasChanged();
    }
}
<!-- ParentComponent.razor -->
@page "/parent"
 
<MyComponent @ref="myComponentRef" />
<button @onclick="ResetChild">重置子組件</button>
 
@code {
    private MyComponent? myComponentRef;
 
    private void ResetChild()
    {
        myComponentRef?.Reset();
    }
}

2、引用 HTML 元素

@page "/element-ref"
 
<input @ref="usernameInput" placeholder="輸入用戶名" />
<button @onclick="FocusInput">聚焦輸入框</button>
 
@code {
    private ElementReference usernameInput;
 
    private async Task FocusInput()
    {
        await usernameInput.FocusAsync();
    }
}

3、在循環中使用 @ref

@page "/loop-ref-example"
 
<h3>循環中使用 ref 示例</h3>
 
<button @onclick="ShowAllMessages" class="btn btn-primary">顯示所有消息</button>
<button @onclick="UpdateAllMessages" class="btn btn-secondary">更新所有消息</button>
 
@foreach (var item in items)
{
    <ChildComponent @ref="componentRefs[item.Id]"
                    Id="item.Id"
                    Message="@item.Message"
                    OnMessageChanged="HandleMessageChanged" />
}
 
@code {
    private List<ItemModel> items = new();
    private Dictionary<int, ChildComponent?> componentRefs = new();
 
    protected override void OnInitialized()
    {
        items = new List<ItemModel>
        {
            new ItemModel { Id = 1, Message = "第一條消(xiao)息" },
            new ItemModel { Id = 2, Message = "第(di)二條消息" },
            new ItemModel { Id = 3, Message = "第三(san)條(tiao)消息" }
        };
        // 預先初始化(hua)字(zi)典
        foreach (var item in items)
        {
            componentRefs[item.Id] = null;
        }
    }
 
    private void ShowAllMessages()
    {
        foreach (var component in componentRefs.Values)
        {
            component?.ShowCurrentMessage();
        }
    }
 
    private void UpdateAllMessages()
    {
        foreach (var item in items)
        {
            if (componentRefs.TryGetValue(item.Id, out var component) && component != null)
            {
                component.UpdateMessage($"更新后的消息(xi) {item.Id}");
            }
        }
    }
 
    private void HandleMessageChanged((int Id, string Message) data)
    {
        Console.WriteLine($"收到消息更新 - ID: {data.Id}, 消息: {data.Message}");
 
        var item = items.FirstOrDefault(i => i.Id == data.Id);
        if (item != null)
        {
            item.Message = data.Message;
            StateHasChanged();
        }
    }
 
    public class ItemModel
    {
        public int Id { get; set; }
        public string Message { get; set; } = string.Empty;
    }
}
<!-- ChildComponent.razor -->
<div class="child-component">
    <h5>子組件 ID: @Id</h5>
    <p>當前消息: <strong>@Message</strong></p>
    <input @bind="currentMessage" @bind:event="oninput" />
    <button @onclick="UpdateMessage" class="btn btn-sm btn-info">更新消息</button>
</div>
 
@code {
    [Parameter]
    public int Id { get; set; }
 
    [Parameter]
    public string Message { get; set; } = string.Empty;
 
    [Parameter]
    public EventCallback<(int Id, string Message)> OnMessageChanged { get; set; }
 
    private string currentMessage = string.Empty;
 
    protected override void OnParametersSet()
    {
        currentMessage = Message;
    }
 
    private async Task UpdateMessage()
    {
        await OnMessageChanged.InvokeAsync((Id, currentMessage));
    }
 
    public void ShowCurrentMessage()
    {
        Console.WriteLine($"組件 {Id} 的消(xiao)息: {Message}");
    }
 
    public void UpdateMessage(string newMessage)
    {
        currentMessage = newMessage;
        UpdateMessage().Wait();
    }
}

4、使用 ref 回調

<CustomInput @ref="SetInputRef" />
 
@code {
    private CustomInput? inputRef;
 
    private void SetInputRef(CustomInput component)
    {
        inputRef = component;
        // 組件引(yin)用設置后的初(chu)始(shi)化邏輯
        component?.Initialize();
    }
}

5、與 JavaScript 互操作

@inject IJSRuntime JSRuntime
 
<div @ref="myDiv" style="width: 100px; height: 100px; background: red;"></div>
<button @onclick="ChangeDivStyle">修改樣式</button>
 
@code {
    private ElementReference myDiv;
 
    private async Task ChangeDivStyle()
    {
        await JSRuntime.InvokeVoidAsync("changeElementStyle", myDiv);
    }
}

對(dui)應的 JavaScript 文件(jian):

// wwwroot/js/site.js
window.changeElementStyle = (element) => {
    element.style.background = 'blue';
    element.style.width = '200px';
};

本章節中用到:IJSRuntime ,后面會(hui)詳細講解。

以上(shang)就是關(guan)于《ASP.NET Core Blazor 核(he)心功能一:Blazor依賴注入與(yu)狀態管理指南(nan)》的全部內容,希望(wang)你有所收獲。關(guan)注我(wo),持續分享(xiang)。

posted @ 2025-10-29 10:07  碼農剛子  閱讀(236)  評論(0)    收藏  舉報