今天要來介紹的是狀態管理,透過狀態管理可以使每個元件都能夠取得一致的狀態,也能透過此方式來進行參數傳遞,加上之前介紹的元件傳值技巧,魔術技巧 - 父子溝通問題魔術技巧 - 傳值技巧,這就是目前 Blazor WebAssembly 元件傳值的三種技巧。


還記得相依性注入魔術技巧內容吧?我們可以放任意服務實體進 DI Container 中,而以 Singleton 為生命週期的服務,可以確保每個需要此服務的元件都得到相同實體,所以我們也可以將資料模型當成服務注入,來進行元件間的傳值。

首先建立一個資料模型:

1
2
3
4
5
// Day23SampleModel.cs
public class Day23SampleModel
{
public string Value { get; set; }
}

然後將該服務新增到 DI:

1
2
// Program.cs
builder.Services.AddSingleton<Day23SampleModel>();

如此一來我們就可以使用 @inject Day23SampleModel Day23SampleModel 來從 di container 中取得同一個 Day23SampleModel 實體如:

1
2
3
4
5
6
7
@* Day23Sample.razor *@
@inject Day23SampleModel Day23SampleModel

<p>
Day23SampleModel.Value: @Day23SampleModel.Value
</p>
<input @bind="Day23SampleModel.Value" />
1
2
3
4
5
6
7
@* Day23Sample2.razor *@
@inject Day23SampleModel Day23SampleModel

<p>
Day23SampleModel.Value: @Day23SampleModel.Value
</p>
<input @bind="Day23SampleModel.Value" />

當任何一個元件修改了 Day23SampleModel.Value 的值,另一個元件也會被修改。


以上就是 .NET 元件狀態管理也是傳值的第三種方式。

但此種狀態管理方式是寫在記憶體中,若想要保留在瀏覽器上,則可以考慮使用 JavaScript 來操作 localStoragesessionStorage 集合:

localStorage:範圍設定為瀏覽器的視窗,如果使用者重載或關閉頁面甚至重新開啟瀏覽器,狀態都會持續存在,且當使用者開啟多個瀏覽器索引標籤,會在索引標籤之間共用狀態,直到明確清除為止,資料會持續存在。

sessionStorage:範圍設定為瀏覽器索引標籤,如果使用者重載此索引標籤,狀態會持續存在,直到使用者關閉索引標籤或瀏覽器,狀態就會遺失,而且如果使用者開啟多個瀏覽器索引標籤,每個索引標籤都有自己獨立的資料版本。

localStorage 來做練習,我們可以撰寫一個 JavaScript 方法如:

1
2
3
4
5
6
7
8
window.exampleJsFunctions = {
setLocalStorageItem: function (key, value) {
localStorage.setItem(key, value);
},
getLocalStorageItem: function (key) {
return localStorage.getItem(key);
}
};

並在初始化時,從 localStorage 取得對應的值,並提供儲存按鈕來更新 localStorage 的內容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<p>
LocalStorage: @localStorageValue
</p>
<input @bind="localStorageValue" />
<button @onclick="Save">Save</button>


@code {
private string localStorageValue;

protected override async Task OnInitializedAsync()
{
localStorageValue = await GetLocalStorageItem("test");
await base.OnInitializedAsync();
}

public async Task Save()
{
await SetLocalStorageItem("test", this.localStorageValue);
}

public async Task SetLocalStorageItem(string key, string value)
{
await JSRuntime.InvokeVoidAsync("exampleJsFunctions.setLocalStorageItem", key, value);
}

public async Task<string> GetLocalStorageItem(string key)
{
return await JSRuntime.InvokeAsync<string>("exampleJsFunctions.getLocalStorageItem", key);
}
}

當然也可以將存取 localStorage 的方法抽成服務,這樣以後有元件需要使用 localStorage 就可以直接注入服務啦。


以上就是狀態管理的方法,若想要參考完整程式碼可以到範本程式碼 - Day23看看唷。

感謝大家的閱讀,我們明天見。

參考資料
ASP.NET Core Blazor 狀態管理