标记帮助器,即 Tag Helpers。这个嘛,就直接翻译了,叫“标记帮助器”,虽然不好听,但只能这样了。当然你翻译为“标记增强器”也行。
所谓标记帮助器,就是针对 HTML 标签(不管是标准的还是自己命名的)进行扩展的做法。它是以 Razor 为基础的,服务于开发人员的。在服务器端用 C# 代码来实现一些需求,并生成 HTML 元素。在 Razor 文档中可以方便书写,VS 、VS Code 等工具还有提示功能。
不太恰当的理解就是把某个 HTML 标记封装为了一种组件,或者补充它原有的功能。不过,理解为一种组件也不算错,只不过不像 Razor 组件那样完整化的封装(里面是一大段HTML),Tag Helper 就是针对某个 HTML 元素的。
老周这篇水文不介绍常用的标记帮助器,毕竟这些大伙们都会用,就是在 Razor 文档中用 @addTagHeler 指令导入的那些类型。如内置的 input、form 元素的帮助器。像咱们常用的像 asp-controller 、asp-action 这些HTML属性就是通过帮助器来扩充的。
老周的想法是:咱们扒一下标记帮助器的底层知识,看能不能发现点啥乐子。生活不易,人世悲苦,“长太息以掩涕兮,哀民生之多艰”,所以得找点乐子充实一下人生。
咱们先聊最抽象的接口:ITagHelperComponent。咦?这货还真是以“Component”结尾,看来确实把标记帮助器认定为一种小型 Razor 组件。看看这接口为我们规范了些啥。
Order 属性:愚蠢的机器把它翻译为【订单】。这个错误很离谱,后果很严重。你要真按订单去理解,那就完了。这个是叫【顺序】,说直接点叫优先级。数值越小就越先被执行,比如,0、3、5,那么,Order 为0的先执行,Order为5的后执行。
Init 方法:看名字就知道这是初始化时被调用的。一般没有特别需要,这方法里不用写什么代码。方法有个 TagHelperContext 类型的参数。唯一能让你修改的是 Items 属性,它是个字典结构,用来存一些自定义数据。这些自定义数据可以在不同的 TagHelper 间传递。有点像 HttpContext.Items。
ProcessAsync 方法:这个是核核核心心心,重要的事延长三拍。各种为 HTML 元素添加属性、生成内容等都在此方法中完成。
实现 ITagHelperComponent 接口的类,在 Razor 文档中是不能被 @addTagHelper 指令导入的。咱们来做来试验。
- [HtmlTargetElement("p")]
- public class PragTagHelper : ITagHelperComponent
- {
- public int Order => 2; //这个优先级可以随意
-
- public void Init(TagHelperContext context)
- {
- // 不用写代码
- }
- public Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
- {
- // 内容之前
- output.PreContent.SetHtmlContent("<strong>");
- // 内容之后
- output.PostContent.SetHtmlContent("</strong>");
- return Task.CompletedTask;
- }
- }
[HtmlTargetElement("p")] 特性表示:我这个标记帮助器是专为<p>元素准备,它只作用于此元素。上述例子的意思是在<p>元素的内部文本呈现之前插入“<strong>”,在内部文本呈现之后插入“</strong>”。就是实现了让段落中的文本加粗显示的效果。PreContent 表示元素内容之前,PostContent 表示元素内容之后。
现在,咱们在 Razor 文档用 @addTagHelper 指令导入一下。
- @page
- @addTagHelper TestApp.PragTagHelper, TestApp
- <p>孔明用枪打死了王司徒</p>
-
- <p>孔明用手雷轰死了王朗</p>
运行程序后,发现不起作用。生成的 HTML 文档没有插入<strong>元素。

然后,我把标记帮助器的代码改一改。这次咱们不实现 ITagHelperComponent 接口,而是 ITagHelper 接口。