ASP.NET Core 3.0 : 二十五. TagHelper

什么是TagHelper?这是ASP.NET Core 中新出现的一个名词,它的作用是使服务器端代码可以在Razor 文件中参与创建和呈现HTML 元素。(ASP.NET Core 系列目录)

一、概述

上面的解释有点拗口?那么换一个名词,HtmlHelper大家都知道吧,在ASP.NET Core中,TagHelper类似HtmlHelper,但可以说是青出于蓝而胜于蓝。那么TagHelper的作用也就大概明白了吧。

首先通过一个例子看一下TagHelper是怎么使用的,看看它和HtmlHelper有什么区别。新建一个Book类:

public class Book
    {
        [Display(Name = "编号")]
        public string Code { get; set; }
[Display(Name = "名称")]
        public string Name { get; set; }
    }

新建对应的Controller和Action:

public class BookController : Controller
    {
        // GET: //
        public IActionResult Index()
        {
            return View(new Book() { Code = "001", Name = "ASP" });
        }
    }

最后就是View了:

@model Book
@{
    Layout = null;
}
@Html.LabelFor(m => m.Name)
@Html.EditorFor(m => m.Name)

for="Name">
for="Name" />

这里分别通过HtmlHelper和TagHelper两种方式实现了一个文本和输入框的显示。查看网页源代码,可以看到二者生成的HTML如下:

for="Name">Name
class="text-box single-line" id="Name" name="Name" type="text" value="ASP" />

for="Name">Name
"text" id="Name" name="Name" value="ASP" />

目前看起来二者差不多,从工作量上来看也是区别不大。现在功能实现了,需要做一些样式处理。简单举个例子,现在希望Book的编号(Code)对应的label的颜色设置为红色,定义了一个css如下:

然后准备把这个样式应用到label上,这时如果是HtmlHelper就很有可能会被问:”class写在哪”,估计好多人都被问过。然后我们告诉他可以这样写:

@Html.LabelFor(m=>m.Name,new {@class="codeColor"})

前端工程师添加后达到了想要的效果,但同时表示记不住这个写法,下次可能还会问。

如果是TagHelper就方便了,告诉他可以像平时给Html的标签添加class一样操作即可,也就是:

for="Name" class="codeColor">

前端工程师表示这种写法”真是太友好了”。同样对于Form及验证,比较一下两种写法的不同,HtmlHelper版:

@using (Html.BeginForm("Index", "Home", FormMethod.Post)){
@Html.LabelFor(m => m.Code)
    @Html.EditorFor(m => m.Code)    @Html.ValidationMessageFor(m => m.Code)    "submit" value="提交" />
}

TagHelper版:

"Index" asp-controller="Home" method="post">
    for="Code">
    for="Code" />
    for="Code">
    "submit" value="提交" />

二、自定义TagHelper

现在有这样的需求,用于显示Book的编号的label不止要添加名为codeColor的css样式,还要给书的编号自动添加一个前缀,例如”BJ”。

对于这样的需求,希望可以通过一个简单的标记,然后由TagHelper自动实现。例如:

"bookCode">1001

自定义了一个属性”show-type”,用于标识这个label的显示类别,”1001″为假定的图书编号。通过这样的设置方式,将来如果需求有变化,需要对编号的显示做更多的修饰,只需修改对应的TagHelper即可,而页面部分不需要做任何调整。

系统提供了方便的自定义TagHelper的方式,就是继承系统提供的TagHelper类,并重写它的Process/ProcessAsync方法,例如下面的例子:

public class LabelTagHelper : TagHelper
    {
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            if (output.Attributes.TryGetAttribute("show-type", out TagHelperAttribute showTypeAttribute))
            {
                if (showTypeAttribute.Value.ToString().Equals("bookCode"))
                {
                    output.Attributes.SetAttribute("class", "codeColor");

                    string content = output.Content.IsModified ? output.Content.GetContent() : (await output.GetChildContentAsync()).GetContent(); ;
                    output.Content.SetContent("BJ" + content);
                }
            }
        }
    }

首先判断label是否被设置了show-type=”bookCode”,然后获取当前label的Content内容,将其添加前缀”BJ”后作为此label的Content的新内容。注意一下Content的获取方式,如果它没有被修改,凭感觉直接通过output.Content.GetContent()获取到的内容是空的。

访问index页面,可以看到改标签已被处理,如下图:

ASP.NET Core 3.0 : 二十五. TagHelper

备注:a.关于获取show-type的值,还可以有其他方式,下文会讲到。

b.从规范化命名的角度,建议将自定义的TagHelper其命名为XXXagHelper这样的格式。

(ASP.NET Core 系列目录)

三、TagHelper的注册

TagHelper自定义之后需要将其注册一下,否则它是不会生效的。打开_ViewImports.cshtml,默认为:

@using TagHelperDemo
@using TagHelperDemo.Models
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

在最下面添加一条

@addTagHelper *, TagHelperDemo

最后添加的这一句话是什么意思呢?也就是将程序集TagHelperDemo(即第二个参数)中的所有TagHelper(第一个参数为”*”,即所有)全部启用。假如还定义了一个PasswordTagHelper,但只想只添加LabelTagHelper,可以这样写:

@addTagHelper TagHelperDemo.TagHelpers. LabelTagHelper, TagHelperDemo

如果想添加所有自定义的TagHelper,但要去除LabelTagHelper呢?

那么可以先添加所有,再去除这个LabelTagHelper。

@addTagHelper *, TagHelperDemo
@removeTagHelper TagHelperDemo.TagHelpers. LabelTagHelper, TagHelperDemo

四、TagHelper的作用范围

在项目中,可能不止使用label标签来显示Book的Code,还有可能会是p、span等类型的标签,现在的需求是,无论是上述哪一种标签,都要实现添加css和前缀的功能。

现在将index.cshtml中新增一个p标签如下:

"bookCode">1002

访问这个页面发现1002未被处理。这是因为我们定义的TagHelper名为LabelTagHelper,在默认的情况下只会处理label标签。当然也可以做特殊设置,例如下面代码的写法:

[HtmlTargetElement("p")]
    public class LabelTagHelper : TagHelper
    {
      //代码省略
    }

通过”[HtmlTargetElement(“p”)]”指定本TagHelper只能被使用于p标签。再次访问此页面,发现p标签被处理了,而label未被处理。这说明这样的显式指定的优先级要高于默认的名称匹配。除了设置指定标签,还可以有一些其他的辅助设置:

[HtmlTargetElement("p", Attributes = "show-type", ParentTag = "div")]
public class LabelTagHelper : TagHelper

可以这样写,会匹配p标签,要求该标签拥有show-type属性,并且父标签为div。这几个条件是”and”的关系。如果还想匹配label标签,可以添加对label的设置,例如下面代码这样:

[HtmlTargetElement("p", Attributes = "show-type", ParentTag = "div")]
[HtmlTargetElement("label", Attributes = "show-type", ParentTag = "div")]
public class LabelTagHelper : TagHelper

这两个HtmlTargetElement的关系是”or”。通过这样的设置,可以极大的缩小目标标签的范围。

但是这样设置之后,这个TagHelper的名字再叫LabelTagHelper就不合适了,例如可以改为BookCodeTagHelper,最终代码如下:

[HtmlTargetElement("p", Attributes = "show-type", ParentTag = "div")]
[HtmlTargetElement("label", Attributes = "show-type", ParentTag = "div")]
public class BookCodeTagHelper : TagHelper
{
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        if (output.Attributes.TryGetAttribute("show-type", out TagHelperAttribute showTypeAttribute))
        {
            if (showTypeAttribute.Value.ToString().Equals("bookCode"))
            {
                output.Attributes.SetAttribute("class", "codeColor");

                string content = output.Content.IsModified ? output.Content.GetContent() :
                                    (await output.GetChildContentAsync()).GetContent(); ;
                output.Content.SetContent("BJ" + content);
            }
        }
    }
}

如果想使个别Html标签屏蔽TagHelper的作用,可以使用”!”。例如下面两个标签:

"bookCode">1001

五、自定义标签

上一节最终形成了一个名为BookCodeTagHelper的TagHelper,我们知道LabelTagHelper是可以按名称默认匹配label标签的,那么是否可以自定义一个BookCode标签呢?在index.cshtml中添加这样的代码:

1003

由于自定义bookcode标签的目的就是专门显示Book的Code,所以也不必添加show-type属性了。然后修改BookCodeTagHelper,修改后的代码如下:

public class BookCodeTagHelper : TagHelper
{
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.Attributes.SetAttribute("class", "codeColor");

        string content = output.Content.IsModified ? output.Content.GetContent() :
                            (await output.GetChildContentAsync()).GetContent(); ;
        output.Content.SetContent("BJ" + content);
    }
}

去掉了两个HtmlTargetElement设置并取消了对show-type的判断,访问index页面查看新建的bookcode标签是否会被处理,结果是没有被处理。这是为什么呢?

这是由于TagHelper会将采用Pascal 大小写格式的类和属性名将转换为各自相应的短横线格式。即”BookCode”对应”book-code”,获取标签的属性值,同样遵循这样的规则。所以将标签改为如下写法即可:

1003

再次运行测试,发现这个新标签被成功处理。查看网页源代码,被处理后的Html代码是这样的:

class="codeColor">TJ1003

如果想将其改变为label,可以在BookCodeTagHelper中通过指定TagName实现:

public class BookCodeTagHelper : TagHelper
{
    public Book Book { get; set; }
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = "label";
        output.Attributes.SetAttribute("class", "codeColor");

        string content = output.Content.IsModified ? output.Content.GetContent() :
                            (await output.GetChildContentAsync()).GetContent(); ;
        output.Content.SetContent(Book.Prefix + content);
    }
}

六、TagHelper与页面之间的数据传递

假如现在的新需求是图书编码的前缀不再固定为”BJ”了,需要在标签中定义,例如这样:

"SH">1003

需要获取prefix的值,在上面的例子中采用的是TryGetAttribute方法,其实还有简单的方式,修改BookCodeTagHelper,代码如下:

public class BookCodeTagHelper : TagHelper
    {
        public string Prefix { get; set; }
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            output.Attributes.SetAttribute("class", "codeColor");

            string content = output.Content.IsModified ? output.Content.GetContent() :
                                (await output.GetChildContentAsync()).GetContent(); ;
            output.Content.SetContent(Prefix + content);
        }
    }

标签中的prefix的值会自动赋值给BookCodeTagHelper.Prefix,是不是更方便了。那么如果是Model中的值呢?假如Book类有一个属性”public string Prefix { get; set; } “,这和传入一个字符串没什么区别,那么可以这样写:

"@Model.Prefix">1003

这种传值方式不止是支持字符串,将Model整体传入也是支持的,将标签修改如下:

"@Model">1003

修改BookCodeTagHelper代码:

public class BookCodeTagHelper : TagHelper
    {
        public Book Book { get; set; }
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            output.Attributes.SetAttribute("class", "codeColor");

            string content = output.Content.IsModified ? output.Content.GetContent() :
                                (await output.GetChildContentAsync()).GetContent(); ;
            output.Content.SetContent(Book.Prefix + content);
        }
    }

七、取消标签输出

前面的几个例子都是对满足条件的标签的修改,TagHelper也可以取消对应标签的输出,例如存在这样一个标签:

"Simple1">

如果不想让它出现在生成的Html中,可以这样处理:

[HtmlTargetElement("div",Attributes = "simple-type")]
public class Simple1TagHelpers : TagHelper
{
    public string SimpleType { get; set; }
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        if (SimpleType.Equals("Simple1"))  //可以是其他一些判断规则
        {
            output.SuppressOutput();
        }
    }
}

八、TagBuilder

在TagHelper中,可以用TagBuilder来辅助生成标签,例如存在如下两个div:

"Simple2">
"Simple3">

想在div中添加Html元素可以这样写:

[HtmlTargetElement("div",Attributes = "simple-type")]
public class Simple1TagHelpers : TagHelper
{
    public string SimpleType { get; set; }
    public override void Process(TagHelperContext context, TagHelperOutput output)
    {
        if (SimpleType.Equals("Simple2"))
        {
            output.Content.SetHtmlContent("Simple2");
        }
        else if (SimpleType.Equals("Simple3"))
        {
            var p = new TagBuilder("p");
            p.InnerHtml.Append("Simple3");
            output.Content.SetHtmlContent(p);
        }
    }
}

通过TagBuilder生成了一个新的p标签,并将它插入到div中。

本文地址:asp.net core: 二十五. taghelper

(ASP.NET Core 系列目录)

Original: https://www.cnblogs.com/FlyLolo/p/ASPNETCore_25.html
Author: FlyLolo
Title: ASP.NET Core 3.0 : 二十五. TagHelper

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/581852/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Tensorflow-逻辑斯蒂回归

    1.交叉熵 逻辑斯蒂回归这个模型采用的是交叉熵,通俗点理解交叉熵 推荐一篇文章讲的很清楚: 因此,交叉熵越低,这个策略就越好,最低的交叉熵也就是使用了真实分布所计算出来的信息熵,因…

    Linux 2023年6月6日
    079
  • 【原创】Linux v4l2框架分析

    背景 Read the fucking source code! –By 鲁迅 A picture is worth a thousand words. –…

    Linux 2023年5月27日
    071
  • podman对容器映像签名和分发

    熟悉podman 如何使用 Podman 对容器映像进行签名和分发 熟悉podman 此示例容器将运行一个非常基本的 httpd 服务器,该服务器仅为其索引页提供服务 [root@…

    Linux 2023年6月7日
    091
  • 文件相关命令

    pwd指令 基本语法:pwd功能:显示当前工作的绝对目录 ls指令 基本语法:ls [选项][目录或者文件]常用选项 -a 显示所有文件及目录 (. 开头的隐藏文件也会列出) -l…

    Linux 2023年6月6日
    070
  • XXE漏洞学习

    0x00 XXE漏洞介绍: 背景:2018-7-4 微信支付SDK漏洞(XXE漏洞),攻击者可以获取服务器中目录结构,文件内容,eg:代码,各种 私钥。敏感数据泄露 0x01什么是…

    Linux 2023年6月6日
    099
  • ansible -自动运维工具

    Ansible-自动运维工具 1.简介 Ansible是一个基于Python开发的配置管理和应用部署工具,现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点,Pubbe…

    Linux 2023年6月13日
    096
  • Nmap 操作手册-完整版

    Nmap – 基础篇 下载Nmap.rpm包 方式一: $ curl -OL https://nmap.org/dist/nmap-7.92-1.x86_64.rpm …

    Linux 2023年6月13日
    089
  • 操作系统实现-简单热身

    博客网址:www.shicoder.top微信:18223081347欢迎加群聊天 :452380935 这次对上次的boot.asm进行代码讲解,也可以对汇编的相关理论进行补充 …

    Linux 2023年6月13日
    078
  • 性能测试

    一.性能测试概述 性能测试概念: 性能测试是指通过特定方式,对被测系统按照一定策略施加压力,获取系响应时间、TPS、资源利用率等性能指标,以期保证生产系统的性能能够满足用户需求的过…

    Linux 2023年6月6日
    083
  • 【Javaweb】JSP标准标签库

    JSTL 1.什么是JSTL 2.版本 3.标签函数库 4.优点 JSTL基本概念 标签(Tag) 标签库(Tag library) 标签库描述文件(Tag Library Des…

    Linux 2023年6月14日
    0135
  • 15、16、17思维导图

    posted @2022-04-24 10:20 20191223张俊怡 阅读(31 ) 评论() 编辑 Original: https://www.cnblogs.com/zzj…

    Linux 2023年6月8日
    0128
  • 网卡的RX Ring和TX Ring

    1 简介 环形缓冲(ring buffer)是NIC处理数据包的一种通用数据结构,出现的原因是现代NIC基本使用DMA进行数据传输,作为一种高效简单[1]的数据结构,环形缓冲很 适…

    Linux 2023年6月7日
    094
  • LeetCode 84.柱状图中最大的矩形 | 单调栈的使用 | 解题思路及算法 Java

    给定(n)个非负整数,用来表示柱状图中每个柱子的高度。每个柱子相邻且宽度为1。求这个柱状图中能容纳的最大矩形的面积。 对于一个柱状图中的最大矩形,我们可以观察出如下性质: 根据上面…

    Linux 2023年6月13日
    0101
  • winServer 监控Serv-U服务脚本(停止自动启动)

    Windows Server 服务器监控服务脚本,每60s查询一次,若服务停止即再启动 Serv-U 服务监控 脚本如下: @echo off rem 定&a…

    Linux 2023年6月7日
    083
  • MySQL PXC集群的实现

    MHA:一主多从,主节点挂了就提升一个从节点作为主节点。 缺点:提升从节点为主节点需要时间,且只有一个节点能进行写操作,所以写的性能不高。 双主架构:两个主节点,两个节点都能进行读…

    Linux 2023年6月7日
    070
  • 跳石板—牛客网

    #include #include #include using namespace std; //计算第i个&#x7684…

    Linux 2023年6月13日
    0105
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球