前面介绍了TagHelper的基本概念和内嵌的TagHelpers,想必大家对TagHelper都有一定的了解。TagHelper看上去有点像WebControl,但它不同于WebControl,没有复杂的生命周期、状态保持、服务器事件以及较高权限,它只能修改自己Tag的内容。有时觉得它更像angular写出来的一个widget,有自己特有的Tag,并对其进行解析生成出widget ui和启动脚本,但是它具有更高的权限,能访问服务器端信息。
在这章,将要介绍如何自定义TagHelper,考虑到内容比较多,会分成几个小章节来介绍。
通过查看内嵌的 TagHelpers的源码 ,发现这些TagHelpers都继承自Microsoft.AspNet.Razor.Runtime.TagHelpers.TagHelper抽象类,而这个类又实现了接口Microsoft.AspNet.Razor.Runtime.TagHelpers.ITagHelper。这个接口是TagHelper最底层的接口,
/// <summary> /// Contract used to filter matching HTML elements. /// </summary> public interface ITagHelper { /// <summary> /// 获取实现ITagHelper接口的类的解析顺序. /// 值小的先用该类来解析。 /// </summary> int Order { get; } /// <summary> /// 根据所给参数context和output异步解析实现ITagHelper的当前类. /// </summary> /// <param name="context">当前HTML Tag的相关信息</param> /// <param name="output">用于生成HTML Tag的HTML元素.</param> /// <returns>用于更新output的Task实例.</returns> Task ProcessAsync(TagHelperContext context, TagHelperOutput output); }
TagHelper类,主要实现了上面接口,添加了一个同步方法来解析当前类,定义如下:
/// <summary> /// Class used to filter matching HTML elements. /// </summary> public abstract class TagHelper : ITagHelper { public virtual int Order { get; } = 0; //同步解析当前TagHelper public virtual void Process(TagHelperContext context, TagHelperOutput output) { } //异步解析当前TagHelper public virtual async Task ProcessAsync(TagHelperContext context, TagHelperOutput output) { Process(context, output); } }
一般自定义TagHelper时,只需要设计的类继承于TagHelper类,重载Process方法,根据context,设置output输出html元素和脚本即可。
自定义的TagHelper类名格式为***TagHelper,其中省略部分***就是该TagHelper应用的Tag。比如我们定义:
public class MyTagHelper: TagHelper { .... }
那么页面上所有Tag是my都会进入到这个类来解析,注意Tag名要是小写。
如果***中包括好几个大写字母,那么对于的Tag名是将大写字母变小写前面加上"-",如果大写字母在第一个位置,那么只需要改成小写,前面不需要加“-”。比如
public class MyFirstOneTagHelper: TagHelper { ... }
那么作用的Tag是
<my-first-one ... ></my-first-one>
我们还可以在类上添加TargetElementAttribute来设置作用的Tag,比如定义如下的类时,其作用的Tag名为my。
[TargetElement("my")] public class MyFirstOneTagHelper: TagHelper { ... }