注意
此版本不是本文的最新版本。 对于当前版本,请参阅本文的 .NET 9 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 NET Core 支持策略。 对于当前版本,请参阅本文的 .NET 9 版本。
除了组件的声明参数和字段外,组件还可以捕获和呈现其他属性。 其他特性可以在字典中捕获,然后在使用 @attributesRazor 指令特性呈现组件时,将其应用到称为“展开”的元素上。 对于定义生成支持各种自定义项的标记元素的组件,此方案非常有用。 例如,为支持多个参数或字段的元素 <input> 单独定义属性可能很繁琐。
属性展开
在下面的 Splat 组件中:
- 第一个
<input>元素 (id="useIndividualParams") 使用单个组件字段。 - 第二个
<input>元素 (id="useAttributesDict") 使用特性展开。
Splat.razor:
@page "/splat"
<PageTitle>SPLAT!</PageTitle>
<h1>Splat Parameters Example</h1>
<input id="useIndividualParams"
maxlength="@maxlength"
placeholder="@placeholder"
required="@required"
size="@size" />
<input id="useAttributesDict"
@attributes="InputAttributes" />
@code {
private string maxlength = "10";
private string placeholder = "Input placeholder text";
private string required = "required";
private string size = "50";
private Dictionary<string, object> InputAttributes { get; set; } =
new()
{
{ "maxlength", "10" },
{ "placeholder", "Input placeholder text" },
{ "required", "required" },
{ "size", "50" }
};
}
@page "/splat"
<PageTitle>SPLAT!</PageTitle>
<h1>Splat Parameters Example</h1>
<input id="useIndividualParams"
maxlength="@maxlength"
placeholder="@placeholder"
required="@required"
size="@size" />
<input id="useAttributesDict"
@attributes="InputAttributes" />
@code {
private string maxlength = "10";
private string placeholder = "Input placeholder text";
private string required = "required";
private string size = "50";
private Dictionary<string, object> InputAttributes { get; set; } =
new()
{
{ "maxlength", "10" },
{ "placeholder", "Input placeholder text" },
{ "required", "required" },
{ "size", "50" }
};
}
@page "/splat"
<input id="useIndividualParams"
maxlength="@maxlength"
placeholder="@placeholder"
required="@required"
size="@size" />
<input id="useAttributesDict"
@attributes="InputAttributes" />
@code {
private string maxlength = "10";
private string placeholder = "Input placeholder text";
private string required = "required";
private string size = "50";
private Dictionary<string, object> InputAttributes { get; set; } =
new()
{
{ "maxlength", "10" },
{ "placeholder", "Input placeholder text" },
{ "required", "required" },
{ "size", "50" }
};
}
@page "/splat"
<input id="useIndividualParams"
maxlength="@maxlength"
placeholder="@placeholder"
required="@required"
size="@size" />
<input id="useAttributesDict"
@attributes="InputAttributes" />
@code {
private string maxlength = "10";
private string placeholder = "Input placeholder text";
private string required = "required";
private string size = "50";
private Dictionary<string, object> InputAttributes { get; set; } =
new()
{
{ "maxlength", "10" },
{ "placeholder", "Input placeholder text" },
{ "required", "required" },
{ "size", "50" }
};
}
@page "/splat"
<input id="useIndividualParams"
maxlength="@maxlength"
placeholder="@placeholder"
required="@required"
size="@size" />
<input id="useAttributesDict"
@attributes="InputAttributes" />
@code {
private string maxlength = "10";
private string placeholder = "Input placeholder text";
private string required = "required";
private string size = "50";
private Dictionary<string, object> InputAttributes { get; set; } =
new()
{
{ "maxlength", "10" },
{ "placeholder", "Input placeholder text" },
{ "required", "required" },
{ "size", "50" }
};
}
@page "/splat"
<input id="useIndividualParams"
maxlength="@maxlength"
placeholder="@placeholder"
required="@required"
size="@size" />
<input id="useAttributesDict"
@attributes="InputAttributes" />
@code {
private string maxlength = "10";
private string placeholder = "Input placeholder text";
private string required = "required";
private string size = "50";
private Dictionary<string, object> InputAttributes { get; set; } =
new Dictionary<string, object>()
{
{ "maxlength", "10" },
{ "placeholder", "Input placeholder text" },
{ "required", "required" },
{ "size", "50" }
};
}
除了id,网页中呈现的<input>元素具有相同的属性:
<input id="useIndividualParams"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
<input id="useAttributesDict"
maxlength="10"
placeholder="Input placeholder text"
required="required"
size="50">
尽管前面的示例使用第一个 <input> 元素的字段(id="useIndividualParams"),但使用组件参数时,相同的行为适用。
任意属性
若要接受任意特性,请定义组件参数,并将 CaptureUnmatchedValues 属性设置为 true:
@code {
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object>? InputAttributes { get; set; }
}
[Parameter] 上的 CaptureUnmatchedValues 属性允许参数匹配所有不匹配任何其他参数的特性。 组件只能使用 CaptureUnmatchedValues 定义单个参数。 与 CaptureUnmatchedValues 一起使用的属性类型必须可以使用字符串键从 Dictionary<string, object> 中分配。 使用 IEnumerable<KeyValuePair<string, object>> 或 IReadOnlyDictionary<string, object> 也是此方案中的选项。
相对于元素特性位置的 @attributes 位置很重要。 将 @attributes 展开到所呈现的元素上时,属性从右到左(从最后到最前)处理,对于任何共有属性,以最先被处理的属性为准。 请考虑以下示例:一个父组件使用一个子组件,其中子组件设置了“extra”属性,父组件在子组件上应用了“extra”属性。
AttributeOrderChild1.razor:
<div @attributes="AdditionalAttributes" extra="5" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
<div @attributes="AdditionalAttributes" extra="5" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
<div @attributes="AdditionalAttributes" extra="5" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
<div @attributes="AdditionalAttributes" extra="5" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
<div @attributes="AdditionalAttributes" extra="5" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object> AdditionalAttributes { get; set; }
}
<div @attributes="AdditionalAttributes" extra="5" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object> AdditionalAttributes { get; set; }
}
AttributeOrder1.razor:
@page "/attribute-order-1"
<PageTitle>Attribute Order 1</PageTitle>
<h1>Attribute Order Example 1</h1>
<AttributeOrderChild1 extra="10" />
<p>
View the HTML markup in your browser to inspect the attributes on
the AttributeOrderChild1 component.
</p>
AttributeOrder1.razor:
@page "/attribute-order-1"
<PageTitle>Attribute Order 1</PageTitle>
<h1>Attribute Order Example 1</h1>
<AttributeOrderChild1 extra="10" />
<p>
View the HTML markup in your browser to inspect the attributes on
the AttributeOrderChild1 component.
</p>
AttributeOrderParent1.razor:
@page "/attribute-order-parent-1"
<AttributeOrderChild1 extra="10" />
AttributeOrderParent1.razor:
@page "/attribute-order-parent-1"
<AttributeOrderChild1 extra="10" />
AttributeOrderParent1.razor:
@page "/attribute-order-parent-1"
<AttributeOrderChild1 extra="10" />
AttributeOrderParent1.razor:
@page "/attribute-order-parent-1"
<AttributeOrderChild1 extra="10" />
AttributeOrderChild1 组件的 extra 属性设置为 @attributes 右侧。 通过附加特性传递时,AttributeOrderParent1 组件的呈现的 <div> 包含 extra="5",因为特性是从右到左(从最后一个到第一个)处理的。在此规则下,第一个“extra”特性会“胜出”,而这个胜出的特性正是 AttributeOrderParent1 组件中硬编码的那个 extra HTML 特性:
<div extra="5" />
在下面的示例中,子组件的<div>中extra和@attributes的顺序是颠倒的。 在此场景中,通过附加特性传递时,AttributeOrderParent2 组件的呈现的 <div> 包含 extra="10",这是因为所处理的第一个“extra”特性是从父组件展开的 extra HTML 特性。
AttributeOrderChild2.razor:
<div extra="5" @attributes="AdditionalAttributes" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
<div extra="5" @attributes="AdditionalAttributes" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
<div extra="5" @attributes="AdditionalAttributes" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
<div extra="5" @attributes="AdditionalAttributes" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object>? AdditionalAttributes { get; set; }
}
<div extra="5" @attributes="AdditionalAttributes" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object> AdditionalAttributes { get; set; }
}
<div extra="5" @attributes="AdditionalAttributes" />
@code {
[Parameter(CaptureUnmatchedValues = true)]
public IDictionary<string, object> AdditionalAttributes { get; set; }
}
AttributeOrder2.razor:
@page "/attribute-order-2"
<PageTitle>Attribute Order 2</PageTitle>
<h1>Attribute Order Example 2</h1>
<AttributeOrderChild2 extra="10" />
<p>
View the HTML markup in your browser to inspect the attributes on
the AttributeOrderChild2 component.
</p>
AttributeOrder2.razor:
@page "/attribute-order-2"
<PageTitle>Attribute Order 2</PageTitle>
<h1>Attribute Order Example 2</h1>
<AttributeOrderChild2 extra="10" />
<p>
View the HTML markup in your browser to inspect the attributes on
the AttributeOrderChild2 component.
</p>
AttributeOrderParent2.razor:
@page "/attribute-order-parent-2"
<AttributeOrderChild2 extra="10" />
AttributeOrderParent2.razor:
@page "/attribute-order-parent-2"
<AttributeOrderChild2 extra="10" />
AttributeOrderParent2.razor:
@page "/attribute-order-parent-2"
<AttributeOrderChild2 extra="10" />
AttributeOrderParent2.razor:
@page "/attribute-order-parent-2"
<AttributeOrderChild2 extra="10" />
父组件的呈现网页中的 <div> 包含 extra="10":
<div extra="10" />