gpt4 book ai didi

blazor - 带有 C# 代码的 Blazor 中的动态 _Hosts.cshtml 文件

转载 作者:行者123 更新时间:2023-12-04 00:59:55 24 4
gpt4 key购买 nike

刚刚使用了 DevExpress 的优秀免费 Blazor 代码来实现自定义 <HEAD>运行时数据:

_Hosts.cshtml(见元素中的代码片段):

    <!DOCTYPE html>
<html lang="en">
<head>
@(await Html.RenderComponentAsync<DocumentMetadataComponent>(RenderMode.ServerPrerendered))
</head>
<body>
<app>
@(await Html.RenderComponentAsync<App>(RenderMode.ServerPrerendered))
</app>
<script src="_framework/blazor.server.js"></script>
</body>

到目前为止效果很好(可以使标题、描述等动态化)。

现在的问题是我必须在那个顶层设置一些变量来过度和解释一次。我想知道使用的 url 并动态提供一些数据。

但据我所知,现在我只能在每个组件中执行两次 (DocumentMetadataComponent + App)。

我在 MainLayout.razor 中获取数据:

<CascadingValue Value="StoreData" Name="StoreData">
@Body
</CascadingValue>

@code{
public StoreCompleteDTO StoreData { get; set; }

protected override async Task OnInitializedAsync()
{
using var tl = new TimeLogger($"MainLayout.razor OnInitializedAsync()");

StoreData = await AppState.GetStoreData(My.StoreId);
}
}

这个 StoreData 变量必须在动态元数据中可用,因为我必须为其他商店选择不同的 CSS 文件...

希望解释清楚。

目标是只调用一次: StoreData = await AppState.GetStoreData(My.StoreId);

因为是网络服务调用,费时间...

谢谢!

最佳答案

我建议在 Blazor 应用程序中提供一些信息的最佳方法是使用服务系统和依赖注入(inject)。

这意味着您可以控制数据的范围(全局? session ?)并使其在您需要的任何页面/组件上可用。写成State容器的形式也有助于使用。这是一个仅设置页面标题的快速示例,但您可以将其扩展到涵盖 <meta>例如。

    /// <summary>
/// A state container for head tags
/// </summary>
public class HeadState
{
/// <summary>
/// Page title
/// </summary>
public string Title => _title;

// internal store
private string _title = "";

/// <summary>
/// Set the page title
/// </summary>
/// <param name="title"></param>
public void SetTitle(string title)
{
if(!string.Equals(_title,title))
{
_title = title;
HeadChanged?.Invoke();
}
}

/// <summary>
/// Event raised when data changes
/// </summary>
public event Action HeadChanged;
}

HeadState类是一个状态容器,允许我们设置页面标题。 title 属性是只读的,因此必须通过 SetTitle 进行设置,这会触发 HeadChanged事件,以便消费者知道它已被修改。我们需要将其注册为 Startup.cs 中的范围服务:

   // declare the HeadState for DI
services.AddScoped<State.HeadState>();

为了实现它,我们修改了 _host.cshtml添加一个在 <head> 中呈现它的组件根据您的问题部分:

<head>
@(await Html.RenderComponentAsync<HeadComponent>(RenderMode.Server))
</head>

HeadComponent注入(inject)状态并处理渲染和更新:

@inject State.HeadState head

<title>@head.Title</title>

@code
{
// although the title is set on loading, if it is changed by a component we
// need to call StateHasChanged to trigger Blazor to rerender since the event
// that triggered it is outside this component
protected override void OnInitialized()
{
head.HeadChanged += () =>
{
StateHasChanged();
};
}
}

要在页面(或任何其他组件!)上测试它,我们只需注入(inject)状态对象并使用它

@page "/"
@inject State.HeadState head

<h1>Head Demo</h1>

<button @onclick='(()=> head.SetTitle("Hello"))'>Set title to Hello</button>
<button @onclick='(()=> head.SetTitle("World"))'>Set title to World</button>

这里我们只是在做一个<title>用于演示目的的标记,但您当然可以添加 <meta>或其他值。我会避免修改 CSS 样式表,因为这可能应该通过 JS 完成,但我不能 100% 确定这是正确的。

关于blazor - 带有 C# 代码的 Blazor 中的动态 _Hosts.cshtml 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59197729/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com