在这篇微软文章中,他们展示了如何将一段Blazor代码提取到一个方法中,以便它可以被重用。他们展示了下面的例子…
<h1>Hello, world!</h1>
@RenderWelcomeInfo
<p>Render the welcome info a second time:</p>
@RenderWelcomeInfo
@code {
private RenderFragment RenderWelcomeInfo = __builder =>
{
<p>Welcome to your new app!</p>
};
}
他们接着解释说,如果你想把这个方法提取到一个单独的.razor
文件中,你可以把它变成static
。
对于他们所展示的简单示例来说,这一切都很好,但如果您想要任何实际的东西,您可能需要向方法传递至少一个参数。
然而,如果你改变他们的SayHello
的例子,接受一个参数…
public static RenderFragment SayHelloName(string name) = __builder => {
<h1>Hello @name</h1>
};
…然后你会得到一个有趣的编译器错误的混合…
=
符号有红色下划线,将鼠标悬停在其上给出错误期望函数体变量
__builder
以红色突出显示,并将鼠标悬停在它上面给出错误无法解析符号__builder
变量
__builder
后面的空间以红色突出显示,并将鼠标悬停在它上面给出错误无法解析符号__builder
nnUnexpected token=>
有一个红色下划线,并悬停在上面给出一个错误不是所有的代码路径返回一个值的lambda表达式的类型'RenderFragment'(这是有趣的,因为返回类型没有一个泛型)方法体中
name
的用法为红色,并显示错误无法解析符号'name'末尾的
};
用红色下划线表示预期的}错误,开始的大括号是类声明。
更令人困惑的是,这些错误中只有第4和第5个出现在错误面板中,尽管措辞略有不同。
按照Telerik的知识库中的示例,我尝试了以下操作…
public static RenderFragment<object> SayHelloName(string name) => context => __builder => {
<h1>Hello @name</h1>
};
然而,当我尝试使用这个…
<div>@SayHelloName("Jim")</div>
…
Microsoft.AspNetCore.Components.RenderFragment`1[System.Object]
…而不是"你好,吉姆";如我所料
谁能解释一下我做错了什么?我如何提取一个RenderFragment方法,参数到一个单独的类?阅读链接到的页面:
RenderFragment委托也可以接受参数。以下组件将消息(message)传递给RenderFragment委托:
<div class="chat">
@foreach (var message in messages)
{
@ChatMessageDisplay(message)
}
</div>
@code {
private RenderFragment<ChatMessage> ChatMessageDisplay = message => __builder =>
{
<div class="chat-message">
<span class="author">@message.Author</span>
<span class="text">@message.Text</span>
</div>
};
}
看起来你需要
public static RenderFragment<string> SayHelloName = name => __builder => {
<h1>Hello @name</h1>
};
如果你想传递更多的参数,把它们包装成一个类型,例如Greeting
:
public class Greeting
{
public string Title { get; set; }
public string Name { get; set; }
}
然后传递Greeting
作为类型参数,类似于文档中的ChatMessage
示例:
public static RenderFragment<Greeting> SayHelloName = greeting=> __builder => {
<h1>Hello @greeting.Title @greeting.Name</h1>
};
或者您可以使用非泛型版本:
public static RenderFragment SayHelloName(string title, string name) => __builder => {
<h1>Hello @greeting.Title @greeting.Name</h1>
};
备选语法:
@page "/razor-template"
@timeTemplate
@petTemplate(new Pet { Name = "Nutty Rex" })
@code {
private RenderFragment timeTemplate = @<p>The time is @DateTime.Now.</p>;
private RenderFragment<Pet> petTemplate = (pet) => @<p>Pet: @pet.Name</p>;
private class Pet
{
public string? Name { get; set; }
}
}
这是来自文档:https://learn.microsoft.com/en-gb/aspnet/core/blazor/components/?view=aspnetcore-6.0#razor-templates
了解RenderFragment
的关键是它是一个委托。片段中的代码将在定义它的类的上下文中运行。
有很多种方法来定义一个。以下是一些:
<h3>RenderFragments.razor</h3>
@code {
public static RenderFragment SayHello = (builder) =>
{
builder.OpenElement(0, "div");
builder.AddContent(1, "Hello");
builder.CloseElement();
};
public static RenderFragment SayHelloAnotherWay => (__builder) =>
{
<div>
Hello Another Way
</div>
};
public static RenderFragment SayHelloAnotherWay1(string name) => (__builder) =>
{
<div>
Hello Another Way @name
</div>
};
public static RenderFragment SayHelloToName(string name) => (builder) =>
{
builder.AddMarkupContent(0, $"<div>Hello {name}</div>");
};
public static RenderFragment<string> SayHello1 => (context) => (builder) =>
{
builder.AddMarkupContent(0, $"<div>Hello {context}</div>");
};
}
和用法:
@page "/"
@RenderFragments.SayHello
@RenderFragments.SayHelloToName("Fred")
@RenderFragments.SayHello1(Name)
@RenderFragments.SayHelloAnotherWay
@RenderFragments.SayHelloAnotherWay1(Name)
@code {
string Name = "John";
}