只需使用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>
到目前为止效果很好(可以使标题,描述等变得动态)。
现在的问题是,我必须在顶层设置一些变量以进行过度解释。 我想知道使用的网址并动态提供一些数据。
但是据我所知,我现在在每个组件(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 =等待AppState.GetStoreData(My.StoreId);
因为这是Web服务调用,并且花费时间...
谢谢!
答案 0 :(得分:1)
我建议在Blazor应用程序中提供某些信息的最佳方法是使用服务系统和依赖注入。
这意味着您可以控制数据的范围(全局?会话?),以及使其在所需的任何页面/组件上可用。以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 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();
};
}
}
要在页面(或任何其他组件!)上对其进行测试,我们只需注入状态对象并使用它
@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%肯定那是正确的。
答案 1 :(得分:0)
我使用以下程序包,该程序包允许您逐页更改元数据。支持Server,ServerPrerendered和WASM!而且超级好用:
https://github.com/jsakamoto/Toolbelt.Blazor.HeadElement
将其与ServerPrerendered应用程序配合使用还意味着该应用程序可以被Google的机器人完全抓取。