原文链接:https://www.cnblogs.com/densen2014/p/16133343.html
只读的localStorage 属性允许你访问一个Document 源(origin)的对象 Storage;存储的数据将保存在浏览器会话中。
存储在 localStorage 的数据可以长期保留
localStorage 中的键值对总是以字符串的形式存储。 (需要注意, 和js对象相比, 键值对总是以字符串的形式存储意味着数值类型会自动转化为字符串类型).
桌面:
Chrome,
Edge,
Firefox,
Internet Explorer,
Opera,
Safari
移动端:
WebView Android,
Chrome Android,
Firefox for Android,
Opera Android,
Safari on iOS,
Samsung Internet
Blazor WebAssembly 用于使用 .NET 生成交互式客户端 Web 应用。 Blazor WebAssembly 使用无插件或将代码重新编译为其他语言的开放式 Web 标准。 Blazor WebAssembly 适用于所有新式 Web 浏览器,包括移动浏览器。
通过 WebAssembly(缩写为 wasm),可在 Web 浏览器内运行 .NET 代码。 WebAssembly 是针对快速下载和最大执行速度优化的压缩字节码格式。 WebAssembly 是开放的 Web 标准,支持用于无插件的 Web 浏览器。
WebAssembly 代码可通过 JavaScript(称为 JavaScript 互操作性,通常简称为 JavaScript 互操作或 JS 互操作)访问浏览器的完整功能 。 通过浏览器中的 WebAssembly 执行的 .NET 代码在浏览器的 JavaScript 沙盒中运行,沙盒提供的保护可防御客户端计算机上的恶意操作。
当 Blazor WebAssembly 应用生成并在浏览器中运行时:
已发布应用的大小(其有效负载大小)是应用可用性的关键性能因素。 大型应用需要相对较长的时间才能下载到浏览器,这会损害用户体验。 Blazor WebAssembly 优化有效负载大小,以缩短下载时间:
Blazor 渐进式 Web 应用 (PWA) 是一种单页应用程序 (SPA),它使用新式浏览器 API 和功能以表现得如桌面应用。
Blazor WebAssembly 是基于标准的客户端 Web 应用平台,因此它可以使用任何浏览器 API,包括以下功能所需的 PWA API:
使用“渐进式”一词来描述这些应用的原因如下:
这次主要以大家谈论比较多的 WASM PWA 为例子,其实 wasm 或 ssr 工程都是可以的完整运行的.
新建项目选择 Blazor WebAssembly 应用
,请选中 渐进式 Web 应用
复选框, 工程命名为 'n04LocalStorage_wasm'
然后右键工程, 管理Nugget程序包
添加Blazored.LocalStorage
库到工程中.
或者.NET CLI
dotnet new blazorwasm -o n04LocalStorage_wasm --pwa dotnet add n04LocalStorage_wasm package Blazored.LocalStorage dotnet sln add n04LocalStorage_wasm/n04LocalStorage_wasm.csproj
ssr参考
dotnet new blazorserver -o n04LocalStorage dotnet add n04LocalStorage package Blazored.LocalStorage dotnet sln add n04LocalStorage/n04LocalStorage.csproj
Program.cs
using Blazored.LocalStorage; builder.Services.AddBlazoredLocalStorage();
注入服务,编写两个方法
@using Blazored.LocalStorage; @code{ [Inject] ILocalStorageService? localStore { get; set; } const string noteKey = "note"; string? noteContent; public async void UpdateLocalStorage() { await localStore!.SetItemAsync(noteKey, noteContent); } public async void ClearLocalStorage() { noteContent = ""; await localStore!.ClearAsync(); } }
InvalidOperationException: JavaScript interop calls cannot be issued at this time. This is because the component is being statically rendered. When prerendering is enabled, JavaScript interop calls can only be performed during the OnAfterRenderAsync lifecycle method.
protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { noteContent = await localStore!.GetItemAsync<string>(noteKey); StateHasChanged(); } }
<textarea @bind="noteContent" /> <br /> <button @onclick="UpdateLocalStorage">Save</button> <button @onclick="ClearLocalStorage">Clear</button>
浏览器按F12,查看应用
,本地存储空间,每次保存按下,观察效果.
重启程序,看看是否能保持上次写入的文字
WeatherForecast类定义
public class WeatherForecast { public DateTime Date { get; set; }=DateTime.Now; public int TemperatureC { get; set; } public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); public string? Summary { get; set; } = "阳光明媚"; public string? SkyColor { get; set; } }
常规CRUD操作
[Inject] ILocalStorageService? localStore { get; set; } private List<WeatherForecast>? forecasts; private WeatherForecast? one = new WeatherForecast(); protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { forecasts = await localStore!.GetItemAsync<List<WeatherForecast>>("forecasts"); if (forecasts == null) { forecasts = new List<WeatherForecast>(); await localStore!.SetItemAsync("forecasts", forecasts); } StateHasChanged(); } } async void Add() { forecasts!.Add(one!); one = new WeatherForecast(); await localStore!.SetItemAsync("forecasts", forecasts); } async void Edit() { await localStore!.SetItemAsync("forecasts", forecasts); } async void Delete(WeatherForecast weather) { forecasts!.Remove(weather); await localStore!.SetItemAsync("forecasts", forecasts); } async void Clear() { forecasts!.Clear(); await localStore!.ClearAsync(); }
页面
<div style="background-color :lightblue"> <p> 日期 <input type="datetime-local" @bind-value="one!.Date" /> </p> <p> 温度 <input type="number" @bind-value="one!.TemperatureC" /> </p> <p> <input @bind-value="one!.Summary" /> </p> <p> <input type="color" @bind-value="one!.SkyColor" /> </p> <button @onclick="Add" class="btn btn-primary">新添</button> </div> @if (forecasts == null) { <p><em>无数据...</em></p> } else { <table class="table"> <thead> <tr> <th>Date</th> <th>Temp. (C)</th> <th>Temp. (F)</th> <th>Summary</th> <th>SkyColor</th> <th></th> <th></th> </tr> </thead> <tbody> @foreach (var forecast in forecasts) { <tr> <td> <input @bind-value="forecast.Date" /> </td> <td> <input @bind-value="forecast.TemperatureC" /> </td> <td>@forecast.TemperatureF</td> <td> <input @bind-value="forecast.Summary" /> </td> <td> <input type="color" @bind-value="forecast.SkyColor" /> </td> <td> <button @onclick="Edit" class="btn btn-primary">编辑</button> </td> <td> <button @onclick="(()=>Delete(forecast))" class="btn btn-warning">删除</button> </td> </tr> } </tbody> </table> <button @onclick="Clear" class="btn btn-danger">清空</button> }
执行看看效果吧
Properties , launchSettings.json
修改这句
"applicationUrl": "https://localhost:7286;http://localhost:5274;https://0.0.0.0:7286;http://0.0.0.0:5274",
手机访问 http://192.168.1.103:5274/
192.168.1.103替换为你机器ip
据我测试,需要部署到域名, demo https://testbrpwa.app1.es/
参考资料 :
PWA 网站离线访问 https://www.jianshu.com/p/f10e72797d25
PWA离线化技术介绍 https://juejin.cn/post/6990937987697606669
Github | Gitee
FreeSql QQ群:4336577(已满)、8578575(已满)、52508226(在线)
BA & Blazor QQ群:795206915、675147445
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名AlexChow(包含链接: https://github.com/densen2014 ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系 。
今日头条 | 博客园 | 知乎 | Gitee | GitHub