[Asp.Net Core] Blazor Server Side 项目实践 - 切换页面时保留状态
2021-03-18 01:27
标签:mes override nts nta none 自带 change ota 怎么办 这是 项目实践系列 , 算是中高级系列博文, 用于为项目开发过程中不好解决的问题提出解决方案的. 不属于入门级系列. 解释起来也比较跳跃, 只讲重点. 因为有网友的项目需求, 所以提前把这些解决方案做出来并分享. Blazor自己是携带一个简单的路由功能的, 当切换Url的时候, 整个通过把RouteData传递给 App.razor 加载 MainLayout , 实现页面刷新的目的. 如果跳转到另外一个页面, 然后再跳回来的时候, 希望原来页面不刷新, 保留之前的状态 , 例如搜索条件, 那么怎么办? 结合视频, 图文观看效果最好 : https://www.bilibili.com/video/BV1g54y1R7uX/ 1. 现在简单说说, 这种情况的源头在哪里. Blazor自带的RouteView是一个控件. 它每次呈现, 都使用 RouteData 属性, 所以它每次生成的 RenderFragment 都是跟着最后的 RouteData 走, 保存来没用. 改造后的 KeepPageStateRouteView , 使用 CreateBody() 方法, 创建出绑定 pagetype 和 routevalue 的 RenderFragement , 为 MainLayout 打下基础 这个字典, Key 是 Url , 而 PageItem 则储存了这个 Url 的多个信息. 范例使用了 TimeSpan GetUrlMaxLifeSpan(string url) 函数来制定页面的生存时间规则. 如果页面的生存时间是 0 , 表示不加进 bodymap , 每次都要全部刷新. 生存时间不为0 , 就储存到 bodymap 里面去. 然后在 @foreach (PageItem eachitem in bodymap.Values.ToArray()) 循环过程中, 把每一个页面 Render 出来. 当前页面, 就显示, 不是当前页面, 则 display:none 所以, 所有要让它活着的 Page , 都得输出. 哪怕用display:none隐藏它. https://www.bilibili.com/video/BV1g54y1R7uX/ 视频杂音的确多, 求推荐一个... [Asp.Net Core] Blazor Server Side 项目实践 - 切换页面时保留状态 标签:mes override nts nta none 自带 change ota 怎么办 原文地址:https://www.cnblogs.com/zhgangxuan/p/d001_keeppagestate.html前言:
问题:
解决过程:
2. App.razor 文件使用了 RouteView 来实现路由
3. routeData是包含页面类型, 以及页面参数的.
4. 然而默认的实现里, RouteView 是不带状态的
5. MainLayout虽然得到了内容的 RenderFragment ,
6. 然而这个 RenderFragment是由RouteView直接绑定到routeData上面去.
7. 所以MainLayout无法得到不同的RenderFragment来显示不同的内容.
8. 要解决这个问题, 首先第一步就是改造 RouteView改造 RouteView
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Components.Rendering;
using System.Reflection;
namespace Microsoft.AspNetCore.Components //use this namepace so copy/paste this code easier
{
public class KeepPageStateRouteView : RouteView
{
protected override void Render(RenderTreeBuilder builder)
{
var layoutType = RouteData.PageType.GetCustomAttribute
改造 MainLayout
@inherits LayoutComponentBase
@inject NavigationManager navmgr
@code{
TimeSpan GetUrlMaxLifeSpan(string url)
{
if (url.Contains("/fetchdata")) // Let /fetachdata always refresh
return TimeSpan.Zero;
if (url.Contains("/counter")) // Let /counter expires in 10 seconds
return TimeSpan.FromSeconds(10);
return TimeSpan.FromSeconds(-1); //other pages never expires
}
class PageItem
{
public string Url;
public RenderFragment PageBody;
public DateTime StartTime = DateTime.Now;
public DateTime ActiveTime = DateTime.Now;
public TimeSpan MaxLifeSpan;
}
Dictionarystring, PageItem> bodymap = new Dictionarystring, PageItem>();
int mainRenderCount = 0;
}
div class="sidebar">
NavMenu />
div>
div class="main">
@{
bool currurlrendered = false;
string currenturl = navmgr.Uri;
PageItem curritem;
if (bodymap.TryGetValue(currenturl, out curritem))
{
curritem.ActiveTime = DateTime.Now;
}
else
{
curritem = new PageItem { Url = currenturl, PageBody = Body };
curritem.MaxLifeSpan = GetUrlMaxLifeSpan(currenturl);
if (curritem.MaxLifeSpan != TimeSpan.Zero)
{
bodymap[navmgr.Uri] = curritem;
}
}
mainRenderCount++;
}
div class="top-row px-4">
#@mainRenderCount
, CurrentUrl : @currenturl
. PageCount : @bodymap.Count
,
button @onclick="StateHasChanged">StateHasChangedbutton>
div>
@foreach (PageItem eachitem in bodymap.Values.ToArray())
{
string pageurl = eachitem.Url;
RenderFragment pagebody = eachitem.PageBody;
string divstyle = "display:none";
if (pageurl == currenturl)
{
divstyle = "";
currurlrendered = true;
}
else if (eachitem.MaxLifeSpan.TotalSeconds > 0 && DateTime.Now - eachitem.ActiveTime > eachitem.MaxLifeSpan)
{
bodymap.Remove(eachitem.Url);
continue;
}
div @key="pageurl" class="content px-4" style="@divstyle">
@pagebody
div>
}
@if (!currurlrendered)
{
div class="content px-4">
@Body
div>
}
div>
MainLayout 里, 最关键的是 Dictionary
没错. 在 Blazor 的 Render 体系里 , 只有输出了, 才有生命. 不输出, 就会被系统释放.
看看视频效果吧. 最后:
文章标题:[Asp.Net Core] Blazor Server Side 项目实践 - 切换页面时保留状态
文章链接:http://soscw.com/essay/65566.html