我们如何在一个单独的代码文件中创建一个可重用的RenderFragment ?



在这篇微软文章中,他们展示了如何将一段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后面的空间以红色突出显示,并将鼠标悬停在它上面给出错误无法解析符号__buildernnUnexpected 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";
}

相关内容

  • 没有找到相关文章