Bob*_*lth 4 asp.net-core asp.net-core-tag-helpers
我正在编写一组针对(以及其他标签)<form>和<input>标签的 ASP.Net Core 标签助手。我的<form>标签助手定义了一个自定义属性,它想要传递给子元素的值。
我读过的所有文章都让这听起来很简单:父标签助手将值存储在context.Items字典中,孩子们从同一个字典中读取它。
这意味着子标签助手在父标签助手之后执行。然而,我发现,在案件<form>和<input>标签帮手,在FormTagHelper执行后的InputTagHelper。
例如,考虑这个 HTML:
<form my-attr='Hello'>
<input asp-for='SomeProperty' />
</form>
Run Code Online (Sandbox Code Playgroud)
我的表单标签助手:
public class FormTagHelper : TagHelper
{
public string MyAttr { get; set; }
public override void Process(TagHelperContext context, TagHelperOutput output)
{
Debug.WriteLine("<form>");
context.Items.Add("my-attr", MyAttr ?? "");
}
}
Run Code Online (Sandbox Code Playgroud)
输入标签助手:
public class InputTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
Debug.WriteLine("<input>");
var valueFromParentForm = context.Items["my-attr"].ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
我希望valueFromParentForm是"Hello",但实际上它会抛出异常,因为 context.Items 字典是空的。
这是怎么回事,我可以做些什么来解决这个奇怪的、由内而外的执行顺序?
除了Process()方法之外,基本标签助手还提供了Init()方法。总结如下:
使用
Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper给定的上下文初始化。补充Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext.Items应在此方法中进行,以确保他们之前执行的孩子正在增加。
只需覆盖此方法并添加您需要的任何内容:
public override void Init(TagHelperContext context)
{
context.Items.Add(1, "Init FormTagHelper");
}
Run Code Online (Sandbox Code Playgroud)
对于您的 html 代码:
<form my-attr='Hello'>
<input asp-for='SomeProperty' />
</form>
Run Code Online (Sandbox Code Playgroud)
让我们有两个标签助手:
[HtmlTargetElement("form")]
public class FormTagHelper : TagHelper
{
public override void Init(TagHelperContext context)
{
context.Items.Add(1, "Init FormTagHelper");
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
context.Items.Add(4, "Process FormTagHelper");
}
}
Run Code Online (Sandbox Code Playgroud)
[HtmlTargetElement("input")]
public class InputTagHelper : TagHelper
{
public override void Init(TagHelperContext context)
{
context.Items.Add(2, "Init InputTagHelper");
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
context.Items.Add(3, "Process InputTagHelper");
}
}
Run Code Online (Sandbox Code Playgroud)
为了更好地理解调用方法的顺序,让我们看一下这张图:
我认为执行顺序是不言自明的。但是红色No access部分呢?让我们从确定Items字典到底是什么以及它是如何工作的开始。它的数字是,IDictionary<object, object>但它不是一本普通的字典。这是一个CopyOnWriteDictionary,它很特别。它有两个底层字典ReadDictionary,WriteDictionary并且它根据当前执行的操作类型(读/写)调用它们中的任何一个。
虽然您可以添加1from FormTagHelper.Init(),但您将无法访问密钥2和3fromFormTagHelper.Process()尽管根据图表它们应该已经存在:
那是因为 的值InputTagHelper被添加到_innerDictionarynot_sourceDictionary然后在FormTagHelper. 这种行为创建了对Items字典的单向访问。儿童标签助手能够访问父母添加的值,但不能以相反的方式访问。
Items执行Init()方法后的字典状态InputTagHelper():
| 归档时间: |
|
| 查看次数: |
718 次 |
| 最近记录: |