图像和 HTML 头组件的 Blazor 加载问题



当我来到我的 blazor 服务器端应用程序时,我感到奇怪的闪烁。

为了更好的用户体验,我实现了一个 GIF 悸动器,但之后加载并不流畅,正如您自己看到的那样:

https://shop6.gastroblitz.de/streetchooser

我的目标是在加载悸动完成后,页面应该完全显示并在一次刷新中:

性能问题的一些想法(但没有以我目前的知识改进的想法......

  1. _Host.cshtml

    • 在区域中预呈现"HtmlHeadComponent"(用于生成特定于域的标题,元数据等(

      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="utf-8" />
      <base href="~/" />
      <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
      <meta name="viewport" content="height=device-height,
      width=device-width, initial-scale=1.0,
      minimum-scale=1.0, maximum-scale=1.0,
      user-scalable=no" />
      <link rel="stylesheet" href="/css/main.css" />
      <link rel="stylesheet" href="https://owlcarousel2.github.io/OwlCarousel2/assets/owlcarousel/assets/owl.carousel.min.css" />
      <link rel="stylesheet" href="https://owlcarousel2.github.io/OwlCarousel2/assets/owlcarousel/assets/owl.theme.default.min.css" />
      <script src="_content/Microsoft.AspNetCore.ProtectedBrowserStorage/protectedBrowserStorage.js"></script>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
      <script src="/js/animations.js"></script>
      <script src="/js/simplebar.min.js"></script>
      <script src="/js/articlePopup.js"></script>
      <script src="/js/accordion.min.js"></script>
      <script src="https://owlcarousel2.github.io/OwlCarousel2/assets/owlcarousel/owl.carousel.js">  </script>
      <script src="/js/my.js"></script>
      <script src="_content/Blazor-Analytics/blazor-analytics.js"></script>
      @(await Html.RenderComponentAsync<HtmlHeadComponent>(RenderMode.ServerPrerendered))
      </head>
      <body>
      <app>
      @(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
      </app>
      <script src="_framework/blazor.server.js"></script>
      <script>
      Blazor.defaultReconnectionHandler._reconnectCallback = function (d) {
      document.location.reload();
      }
      </script>
      <script src="https://cdn.syncfusion.com/ej2/17.4.43/dist/ej2.min.js"></script>
      <script src="https://cdn.syncfusion.com/ej2/17.4.43/dist/ejs.interop.min.js"></script>
      </body>
      </html>
      
  2. App.razor

    • 在这里,我只是从加载每个数据时开始(请参阅 if 语句 + 许多级联参数来处理子组件中的数据更改(

      <Router AppAssembly="@typeof(Program).Assembly">
      <Found Context="routeData">
      @if (AppState.StoreData != null &&
      AppState.MultiStoreData != null &&
      AppState.StoreChooserData != null)
      {
      <CascadingValue Value="AppState.StoreData" Name="StoreData">
      <CascadingValue Value="AppState.MultiStoreData" Name="MultiStoreData">
      <CascadingValue Value="AppState.StoreChooserData" Name="StoreChooserData">
      <CascadingValue Value="AppState.BasketData" Name="BasketData">
      <CascadingValue Value="AppState.CheckoutData" Name="CheckoutData">
      <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
      <GoogleAnalytics TrackingId="@AppState.StoreData?.StoreContainer?.Store?.GoogleAnalyticsId" />
      </CascadingValue>
      </CascadingValue>
      </CascadingValue>
      </CascadingValue>
      </CascadingValue>
      }
      else
      {
      <img class="center" src="/img-dev/ajax-loader.gif" />
      }
      </Found>
      <NotFound>
      <LayoutView Layout="@typeof(MainLayout)">
      <p>Sorry, there's nothing at this address.</p>
      </LayoutView>
      </NotFound>
      

  3. 最后一步是给定的storechooser页面,该页面也仅在所有数据可用时加载内容

    @page "/streetchooser"
    @inherits StreetChooserBase
    @if (StoreChooserData != null && MultiStoreData != null)
    {
    <div class="slider" id="home">
    <div id="owl-demo" class="owl-carousel owl-theme pitch_img">
    @if (!string.IsNullOrEmpty(MultiStoreData.MultiStore.StreetChooserImage1))
    {
    <div class="item">
    <img src="img/@StoreData?.StoreContainer?.Store?.Key/@MultiStoreData.MultiStore.StreetChooserImage1" alt="" class="pitch_img" />
    </div>
    }
    @if (!string.IsNullOrEmpty(MultiStoreData.MultiStore.StreetChooserImage2))
    {
    <div class="item">
    <img src="img/@StoreData?.StoreContainer?.Store?.Key/@MultiStoreData.MultiStore.StreetChooserImage2" alt="" class="pitch_img" />
    </div>
    }
    @if (!string.IsNullOrEmpty(MultiStoreData.MultiStore.StreetChooserImage3))
    {
    <div class="item">
    <img src="img/@StoreData?.StoreContainer?.Store?.Key/@MultiStoreData.MultiStore.StreetChooserImage3" alt="" class="pitch_img" />
    </div>
    }
    @if (!string.IsNullOrEmpty(MultiStoreData.MultiStore.StreetChooserImage4))
    {
    <div class="item">
    <img src="img/@StoreData?.StoreContainer?.Store?.Key/@MultiStoreData.MultiStore.StreetChooserImage4" alt="" class="pitch_img" />
    </div>
    }
    @if (!string.IsNullOrEmpty(MultiStoreData.MultiStore.StreetChooserImage5))
    {
    <div class="item">
    <img src="img/@StoreData?.StoreContainer?.Store?.Key/@MultiStoreData.MultiStore.StreetChooserImage5" alt="" class="pitch_img" />
    </div>
    }
    </div>
    <div class="slider_content ">
    <div class="container">
    <div class="row ">
    <div class="col-sm-5">
    @if (StoreChooserData != null && MultiStoreData != null)
    {
    <EditForm Model="@StoreChooserData">
    <div class="search-section">
    <div class="search-logo">
    <img src="img/@StoreData?.StoreContainer?.Store?.Key/@StoreData?.StoreContainer?.Store?.LogoUrl" alt="" />
    </div>
    <p>Sushi und mehr online bestellen und abholen oder direkt nach Hause liefern lassen.</p>
    <div class="row">
    <div class="col-sm-6">
    <div class="select-location @(StoreChooserData.OrderType == "1" ? "active" : "")"
    @onclick="OrderTypeChangedToDelivery"> Lieferung</div>
    </div>
    <div class="col-sm-6">
    <div class="select-location @(StoreChooserData.OrderType == "2" ? "active" : "")"
    @onclick="OrderTypeChangedToPickup"> Selbstabholer</div>
    </div>
    </div>
    <div class="search-rest">
    <label>Plz / Ort </label>
    <EjsComboBox Value="@StoreChooserData.PostcodeCitySite"
    ModelType="@typeof(Db_DeliveryStreet)"
    Placeholder="Ort eingeben"
    ShowClearButton="true"
    AllowCustom="true"
    AllowFiltering="true"
    FilterType="FilterType.Contains"
    NoRecordsTemplate="<div>Keine Ergebnisse</div>"
    DataSource="@MultiStoreData.DeliveryZones">
    <AutoCompleteEvents TValue="string" ValueChange="PostcodeCityChanged"></AutoCompleteEvents>
    <ComboBoxFieldSettings GroupBy="Postcode" Value="FullName"></ComboBoxFieldSettings>
    <ComboBoxTemplates>
    <GroupTemplate Context="Item">
    <span class="group">@((Item as Db_DeliveryStreet).Postcode)</span>
    </GroupTemplate>
    <ItemTemplate Context="Item">
    <span><span class='name'>@((Item as Db_DeliveryStreet).CitySite)</span><span class='minOrderValue'>@($"ab {(Item as Db_DeliveryStreet).MinOrderValue?.ToString("f2")}€")</span></span>
    </ItemTemplate>
    </ComboBoxTemplates>
    </EjsComboBox>
    <ValidationMessage For="@(() => StoreChooserData.PostcodeCitySite)">
    </ValidationMessage>
    </div>
    <div class="search-rest">
    <label>Straße / Hausnr. </label>
    <EjsComboBox Value="@StoreChooserData.Street"
    ModelType="@typeof(StreetItem)"
    Placeholder="Straße eingeben"
    ShowClearButton="true"
    AllowCustom="true"
    AllowFiltering="true"
    FilterType="FilterType.Contains"
    NoRecordsTemplate="<div>Keine Ergebnisse</div>"
    DataSource="@Streets">
    <AutoCompleteEvents TValue="string" ValueChange="StreetChanged"></AutoCompleteEvents>
    <ComboBoxFieldSettings Value="Name"></ComboBoxFieldSettings>
    </EjsComboBox>
    <ValidationMessage For="@(() => StoreChooserData.Street)"></ValidationMessage>
    </div>
    <div class="search-rest">
    <button class="search-send-btn" @onclick="@GoToNext">weiter </button>
    </div>
    </div>
    </EditForm>
    }
    </div>
    </div>
    </div>
    </div>
    </div>
    <FooterComponent />
    }
    

认为一个问题是图像在我的代码中很晚才被请求并产生闪烁......

但是,如何才能以更好的方式处理这个问题呢?或者也许另一点可能是一些问题。

希望你明白我的意思。

提前感谢!

我正在使用MemoryCache来防止因使用RenderMode.ServerPrerendered引起的闪烁。此问题在此线程中讨论。

通过在服务器上的预呈现和呈现阶段之间缓存结果集,可以避免过滤问题。希望他们在下一个版本中以某种方式修复它。

在服务器端 blazyor 上使用内存更简单、更好 为此缓存。

  • 它避免了国家绊倒。
  • 它可以与 react/redux 方法结合使用,您只需传递存储的 id 并将存储放入内存缓存中,其中包含 id,然后用于在应用重新连接时检索应用商店 并生成与预渲染相同的渲染。

下面的一个例子是修改后的天气服务,它显示它 不会导致闪烁。

public WeatherForecastService(IMemoryCache memoryCache)
{
MemoryCache = memoryCache;
}
public IMemoryCache MemoryCache { get; }
public Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
{
return MemoryCache.GetOrCreateAsync(startDate, async e =>
{
e.SetOptions(new MemoryCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(30) });
var rng = new Random();
await Task.Delay(TimeSpan.FromSeconds(10));
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
}).ToArray();
});
}
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

线路await Task.Delay(TimeSpan.FromSeconds(10));仅用于演示目的,当然没有必要等待 10 秒。

最新更新