在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
这篇博文ASP.NET MVC Core的TagHelper(基础篇)介绍了TagHelper的基本概念和创建自定义TagHelper的方式,接着继续介绍一些新的看起来比较高级的特性。(示例代码紧接着上一遍博文) 一、使用自定义的标记元素 之前基础篇介绍的TagHelper的功能是给已有的HTML元素提供一个自定义的属性标记,然后服务器认出这个标记后,将标记转化成最终的HTML。这里将要介绍的功能是,定义个全新的Tag,看起来跟普通的HTML元素一样。是不是觉得很熟悉呢(前提是你用过AngularJS),完全类似于AngularJS的强大的元素定义功能。 比如我们这里创建一个新的标记元素,formbutton,使用方式如下 <formbutton type="submit" bg-color="danger" /> 当然这个标记完全不是HTML内部定义的,浏览器也不能认出这是个啥玩意。 这个Tag跟自定义的属性标记一样,都会被MVC Core框架识别出来,然后转化成最终的HTML。 接下来我们创建这个TagHelper 在TagHelpers文件夹新建一个类 [HtmlTargetElement("formbutton")] public class FormButtonTagHelper : TagHelper { public string Type { get; set; } = "Submit"; public string BgColor { get; set; } = "primary"; public override void Process(TagHelperContext context, TagHelperOutput output) { output.TagName = "button"; output.TagMode = TagMode.StartTagAndEndTag; output.Attributes.SetAttribute("class", $"btn btn-{BgColor}"); output.Attributes.SetAttribute("type", Type); output.Content.SetContent(Type == "submit" ? "Add" : "Reset"); } } 这个class定义的两个属性Type和BgColor,如大部分的猜想,这两个属性会匹配成html中定义的属性,然后把值自动赋给TagHelper Instance中的属性。 Process一连串的output调用也比较直接,大概意思是要生成一个button元素,并且根据用户提供的Type和BgColor生成class和type两个html属性的值。 其中SetContent是要设置需要输出的内容,由于TagMode是StartTagAndEndTag,所以内容会显示在标记之间。 接下来在home/create这个页面使用我们的自定义标记 @model City 我们使用formbuttion分别创建了一个submit和reset按钮,并且给submit按钮设置了danger样式 那么这两个按钮输出后的html分别是 <button class="btn btn-danger" type="submit">Add</button> <button class="btn btn-primary" type="reset">Reset</button> 这是创建一个基本的自定义TagHelper的使用方式。 二、在目标元素之前或者之后插入内容 上一个栗子,比较中规中矩,实际上我们经常需要给元素前后插入一些内容,通常是一些外围包含元素。比如有如下元素 <div title="Cities"></div> 我们希望这个标记在输出成html的时候能在前后都自动加上一个div class=panel-body的色块,那么我么可以利用TagHelperOutput提供的方法实现。 可以创建如下的自定义TagHelper来说明 在TagHelpers文件夹新建类ContentWrapperTagHelper [HtmlTargetElement("div", Attributes = "title")] public class ContentWrapperTagHelper : TagHelper { public bool IncludeHeader { get; set; } = true; public bool IncludeFooter { get; set; } = true; public string Title { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output) { output.Attributes.SetAttribute("class", "panel-body"); var title = new TagBuilder("h1"); title.InnerHtml.Append(Title); var container = new TagBuilder("div"); container.Attributes["class"] = "bg-info panel-body"; container.InnerHtml.AppendHtml(title); if (IncludeHeader) { output.PreElement.SetHtmlContent(container); } if (IncludeFooter) { output.PostElement.SetHtmlContent(container); } } } 1.这里指定了TagHelper的应用范围是包含了title属性的div元素 2.分别提供了IncludeHeader和IncludeFooter的属性,默认都是true 3.然后分别使用PreElement和PostElement设置前后内容 我们把这个标签应用在_Layout文件中 <!DOCTYPE html> 运行就能看到头部和底部分别都输出了一个色块,并且包含了标题内容 三、在已有标记内容中插入内容 上一个栗子讲的是插入元素,这里演示一下插入内容到标签中,比如已有标签里面已经有内容了,可以在内容之前或者之后插入内容。 在TagHelpers目录新建一个TableCellTagHelper类 [HtmlTargetElement("td", Attributes = "wrap")] public class TableCellTagHelper : TagHelper { public override void Process(TagHelperContext context, TagHelperOutput output) { output.PreContent.SetHtmlContent("<b><i>"); output.PostContent.SetHtmlContent("</i></b>"); } } 通过使用TagHelperOutput的PreContent和PostContent,分别在已有内容的前后插入了一段html标记包裹,这个TagHelper只会用于带有wrap属性的td标记。 把这个标记用在Home/Index.cshtml页面,把city的名称的td加入wrap属性即可 @model IEnumerable<City> 运行后可以看到已有的内容都被<i><b></b></i>包裹起来,呈现的是加粗和斜体的效果。
四、使用ViewModel提供的属性值 在VIew里面输出ViewModel的值,经常会用到一些强类型的帮助方法,比如asp-for="Name"等,那么实际上就会读取ViewModel的Name的属性值。 自定义的TagHelper也支持这种方式,我们来看一下如何调用,还是继续在TagHelpers目录新建一个类,如下 LabelAndInputTagHelper [HtmlTargetElement("label", Attributes = "helper-for")] [HtmlTargetElement("input", Attributes = "helper-for")] public class LabelAndInputTagHelper : TagHelper { public ModelExpression HelperFor { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output) { if (output.TagName == "label") { output.TagMode = TagMode.StartTagAndEndTag; output.Content.Append(HelperFor.Name); output.Attributes.SetAttribute("for", HelperFor.Name); } else if (output.TagName == "input") { output.TagMode = TagMode.SelfClosing; output.Attributes.SetAttribute("name", HelperFor.Name); output.Attributes.SetAttribute("class", "form-control"); if (HelperFor.Metadata.ModelType == typeof(int?)) { output.Attributes.SetAttribute("type", "number"); } } } } 这个TagHelper的作用用,将for属性应用到label和input元素上,实现常见的点击label后聚焦到input的功能。 这里一个关键属性是HelperFor,用来读取ViewModel提供的属性的信息,它的类型是ModelExpression,看起来比较高级,用它可以很方便得到ViewModel的信息。 我们把这个TagHelper应用到Home/Create.cshtml页面中 比如之前我们是这样写的 <label for="Name">Name:</label> <input class="form-control" name="Name" /> 现在用了标记之后就可以简化成如下 <label helper-for="Name"/> <input helper-for="Name"/> 看起来更加的整洁,和符合强迫症程序员的口味。
五. TagHelper之前相互通讯协同 两个不同的TagHelper之前实际上可以通过共享数据的方式实现协同,当然共享数据的方式很多啊,比如粗暴一点的用数据,什么Session之类的(经常面试被问到的Asp.net页面传递有哪些方法啊,通常是老家伙装13的样子在问) 当然我们不会用数据或者Session去保存共享的数据,TagHelperContext为我们提供了一个便利的实现方式,类似于HttpContent.Items,直接看看例子。 在TagHelpers文件夹新建一个CoordinatingTagHelpers文件 [HtmlTargetElement("div", Attributes = "theme")] public class ButtonGroupThemeTagHelper : TagHelper { public string Theme { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output) { context.Items["theme"] = Theme; } } [HtmlTargetElement("button", ParentTag = "div")] [HtmlTargetElement("a", ParentTag = "div")] public class ButtonThemeTagHelper : TagHelper { public override void Process(TagHelperContext context, TagHelperOutput output) { if (context.Items.ContainsKey("theme")) output.Attributes.SetAttribute("class", $"btn btn-{context.Items["theme"]}"); } } 这个文件包含两个TagHelper,第一个是定义了div标签,它在context.Items里设置了theme的值,然后在另外一个TagHelper中读取items的值。 用法简单到没有朋友 <div theme="primary"> 里面的button的样式会根据外层theme的值来设置对应的样式,比如设置theme="Danger",里面的按钮显示为如下样式
六. 禁止内容输出 最后要介绍的是禁止内容输出。禁止内容输出很多方法,最简单的不显示或者加个if else判断。 这里使用TagHelperOutput提供的SuppressOutput方法。 新建如下TagHelper [HtmlTargetElement(Attributes = "show-for-action")] public class SelectiveTagHelper : TagHelper { public string ShowForAction { get; set; } [ViewContext] [HtmlAttributeNotBound] public ViewContext ViewContext { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output) { if (!ViewContext.RouteData.Values["action"].ToString() .Equals(ShowForAction, StringComparison.OrdinalIgnoreCase)) { output.SuppressOutput(); } } } 这个TagHelper定义了其标签内容只有在当前Action跟目标Action一致的时候在显示内容,否则调用Suppress禁止内容输出 比如如下html标记 <div show-for-action="Index" class="panel-body bg-danger"> 指定了只有在Index action下才显示important Message
示例代码路径 https://github.com/shenba2014/AspDotNetCoreMvcExamples/tree/master/CustomTagHelper |
请发表评论