我们如何在单独的代码文件中创建可重用的 RenderFragment?
How do we create a reusable RenderFragment in a separate code file?
在 this Microsoft article 中,他们展示了如何将一段 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>
};
...然后你会得到一个有趣的编译器错误组合...
=
符号有红色下划线,悬停在它上面会报错 Function body expected
变量__builder
以红色高亮显示,鼠标悬停在上面报错无法解析符号__builder
变量__builder
后面的space用红色高亮显示,悬停在上面会报错无法解析符号__builder
\n\nUnexpected令牌
=>
有红色下划线,将鼠标悬停在上面会出现错误 并非所有代码路径 return lambda 表达式中的值 'RenderFragment'(这很有趣,因为 return 类型没有通用类型)
方法体中name
的用法为红色错误无法解析符号'name'
最后的 };
带有红色下划线并显示错误 } expected,左大括号是 class声明。
更令人困惑的是,这些错误中只有第 4 个和第 5 个出现在错误面板中,尽管措辞略有不同。
按照 Telerik's KB 中的示例,我尝试了以下...
public static RenderFragment<object> SayHelloName(string name) => context => __builder => {
<h1>Hello @name</h1>
};
但是,当我尝试使用它时...
<div>@SayHelloName("Jim")</div>
...页面呈现如下...
Microsoft.AspNetCore.Components.RenderFragment`1[System.Object]
...而不是我预期的“Hello Jim”。
谁能解释我做错了什么?如何提取将参数带入单独 class?
的 RenderFragment 方法
阅读您链接到的页面的更下方:
RenderFragment delegates can also accept parameters. The following
component passes the message (message) to the RenderFragment delegate:
<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>
};
或者您可以使用 non-generic 版本:
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://docs.microsoft.com/en-gb/aspnet/core/blazor/components/?view=aspnetcore-6.0#razor-templates
了解 RenderFragment
的关键是它是一个委托。片段中的代码将 运行 在其定义的 class 的上下文中。
有很多方法可以定义一个。这里有一些:
<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";
}
在 this Microsoft article 中,他们展示了如何将一段 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>
};
...然后你会得到一个有趣的编译器错误组合...
=
符号有红色下划线,悬停在它上面会报错 Function body expected变量
__builder
以红色高亮显示,鼠标悬停在上面报错无法解析符号__builder
变量
__builder
后面的space用红色高亮显示,悬停在上面会报错无法解析符号__builder
\n\nUnexpected令牌=>
有红色下划线,将鼠标悬停在上面会出现错误 并非所有代码路径 return lambda 表达式中的值 'RenderFragment'(这很有趣,因为 return 类型没有通用类型)方法体中
name
的用法为红色错误无法解析符号'name'最后的
};
带有红色下划线并显示错误 } expected,左大括号是 class声明。
更令人困惑的是,这些错误中只有第 4 个和第 5 个出现在错误面板中,尽管措辞略有不同。
按照 Telerik's KB 中的示例,我尝试了以下...
public static RenderFragment<object> SayHelloName(string name) => context => __builder => {
<h1>Hello @name</h1>
};
但是,当我尝试使用它时...
<div>@SayHelloName("Jim")</div>
...页面呈现如下...
Microsoft.AspNetCore.Components.RenderFragment`1[System.Object]
...而不是我预期的“Hello Jim”。
谁能解释我做错了什么?如何提取将参数带入单独 class?
的 RenderFragment 方法阅读您链接到的页面的更下方:
RenderFragment delegates can also accept parameters. The following component passes the message (message) to the RenderFragment delegate:
<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>
};
或者您可以使用 non-generic 版本:
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://docs.microsoft.com/en-gb/aspnet/core/blazor/components/?view=aspnetcore-6.0#razor-templates
了解 RenderFragment
的关键是它是一个委托。片段中的代码将 运行 在其定义的 class 的上下文中。
有很多方法可以定义一个。这里有一些:
<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";
}