• 【ASP.NET Core】标记帮助器——元素筛选


    前一篇中老周从标记帮助的底层介绍关键性的接口,如 ITagHelper ,它是一个标志,用于识别哪些类属于 Tag Helper。

    标记帮助器毕竟是针对 HTML 标记的,所以得筛选。说白了就是我写的这个帮助器在哪些 HTML 标记上起作用。这就需要拿出一个特性类。

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
    public sealed class HtmlTargetElementAttribute : Attribute

    咱们看到,这个特性只能应用到类上面。啥类?当然是从 TagHelper 派生的类(或者实现 ITagHelper 接口的类)。

    在使用时,我们一般会调用带一个字符串参数的构造函数。

    public HtmlTargetElementAttribute(string tag)

    用字符串说明你这个帮助器用到哪个标记上。比如

    [HtmlTargetElement("div")]
    [HtmlTargetElement("a")]
    [HtmlTargetElement("p")]
    [HtmlTargetElement("form")]

    这个应该好理解,如果设置的是“div”,表明我这个帮助器是在

    元素上起作用的。

    当然,这个特性类也有无参数的构造函数。如果调用此构造函数,即未指定 HTML 标记。

    [HtmlTargetElement]

    这相当于把标记指定为“*”(星号)。

    [HtmlTargetElement("*")]

    意思就是我这个帮助器是面向所有 HTML 元素的,通吃。

    也许各位大伙伴也发现了,这厮筛选元素的方式很像 CSS 的选择器。对,的确是的。但是,得记住:这货是面向标记的,而不是特定某个元素的。啥意思?就是说你不能用元素 id 去筛选,比如这样就不行。

    [HtmlTargetElement("#abc")]

    不过,可以根据属性筛选,比如

    [HtmlTargetElement("span", Attributes = "[data=1]")]

    属性筛选要放在 Attributes 属性上,不要和标记名称写一起。上面代码是筛选有 data = "1" 的span标记。即

    <span data="1">...span>

    ----------------------------------------------------------------------------------------------------------

    好了,概念的东西说得有点多了,咱们来做个例子。

    这里老周写了一个面向 的标记帮助器,把此标记的内容中带有中括号的文本掩盖掉。比如

    <span>我是一只小小[小鸟]span>

    被中括号裹起来的是“小鸟”,所以把它掩盖掉,变成“我是一只小小**”,或“我是一只小小##”。

    标记帮助器代码如下:

    复制代码
    namespace Test;
    
    [HtmlTargetElement("span")]
    public class ReplaceCharTagHelper : TagHelper
    {
        public char MaskChar { get; set; } = '*';
    
        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            // 下面这行代码的作用是让标记执行它的子级
            // 这样我们才能获取到目标元素的内容
            var tagContent = await output.GetChildContentAsync();
            string text = tagContent.GetContent();
            int count = text.Length;
            if(count > 0)
            {
                // 原字符串的索引不能set,因此先转为char数组
                var chararr = text.ToArray();
                // 这个bool变量是个开关
                // 即遇到“[”字符时开,遇到“]”字符时关
                // 后面在替换字符时用得上
                bool flag = false;
                for(int x = 0; x < count; x++)
                {
                    char c = chararr[x];
                    if(c == '['){
                        flag = true;    //
                        continue;
                    }
                    else if(c == ']')
                    {
                        flag = false;   //
                        continue;
                    }
                    if(flag){   
                        // 如果“开”说明进入了中括号内,表示字符可替换
                        // 如果“关”说明已经出了中括号,就别替换了
                        chararr[x] = MaskChar;
                    }
                }
                // 构建新的字符串
                string newStr = new string(chararr);
                // 把“[”、“]”两个字符清除
                newStr = newStr.Replace("[", "").Replace("]", "");
                // 用新的内容替换标记原来的内容
                output.Content.SetContent(newStr);
            }
        }
    }
    复制代码

    下面老周解释一下。

    1、这个帮助器是面向元素的。

    2、MaskChar 属性允许咱们自己设置掩盖文本的字符,算是一掩码吧。

    3、在处理HTML输出时注意这一句:

    var tagContent = await output.GetChildContentAsync();

    为什么要调用这一句呢?因为咱们要修改之间的内容,你如果直接访问 output.Content.GetContent 是什么也获取不到的,因为此时的子级内容还没有呈现。所以啊,为了能获取到待处理的文本,咱们要先调用 GetChildContentAsync 方法。这个方法会先执行子级内容,然后返回内容。

    4、这里老周的处理思路是这样的。string 类型的实例虽然是 char 的集合,但其索引器是 get 的,不支持 set,即咱们不能直接修改其中某个字符。办法只能先 ToArray 让文本变成 char[],然后循环里面每个字符。如果遇到“[”,表明中括号开始了(把 flag 设为 true),从下一个字符起就是中括号包含的内容,需要掩盖掉;如果遇到“]”字符,说明要离开中括号的包围圈(flag 设为 false),从下一个字符起就不是中括号中的字符,不能掩盖。最后,用修改过的 char[] 产生新的字符串对象,为了打扫战场,还要把“[”、“]”去掉。这个直接用 Replace 就行了。

    5、调用 output.Content.SetContent 方法用新的内容替换原有的内容。

    在 Razor 文档中,用 @addTagHelper 指令导入刚自定义的标记帮助器。

    @addTagHelper Test.ReplaceCharTagHelper, TestApp

    这里 TestApp 是标记帮助器所在程序集的名称,一般与项目名字相同。我这个项目就叫 TestApp。

    来,测试一下。

    复制代码
    @page
    @addTagHelper Test.ReplaceCharTagHelper, TestApp
    
    mask-char="@('#')">
        明天我们去[骑行]
    
    
    mask-char="@('*')">
        ,顺便买几吨[啤酒]喝
    
    复制代码

    mask-char 就是类中定义的 MaskChar 属性,ASP.NET Core 会识别像 mask-char 这样的写法,主要是语义明了。在设置 MaskChar 属性时要把值写在 @( ) 中,不能写成 mask-char="*",否则编译不通过的。="*" Razor 引擎默认解析为 string 类型而不是 char,而写在 @() 中就成了 C# 表达式,编译器能识别。

    运行后的结果如下。

    咱们也可以让标记帮助器支持更多元素。

    [HtmlTargetElement("span")]
    [HtmlTargetElement("div")]
    [HtmlTargetElement("p")]
    public class ReplaceCharTagHelper : TagHelper

     

  • 相关阅读:
    软件测试学习笔记丨Selenium复用已打开浏览器
    CPSC上月召回265万件产品,其中多款国产儿童睡衣不符合可燃性标准被召回
    英语——分享篇——每日100词——601-700
    R语言使用oneway.test函数执行单因素方差分析(One-Way ANOVA)、使用aov函数执行单因素方差分析(aov函数默认组间方差相同)
    问题:conda删除虚拟环境,报错no package names supplied
    第三章:人工智能深度学习教程-人工智能与机器学习与深度学习之间的区别
    金仓数据库KingbaseES 绑定变量窥探机制
    Java:学习技术栈整理
    数据宝董事长汤寒林分享保险行业数据产品场景案例
    WordPress 插件推荐:菜单缓存插件——Menu Caching
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/17134603.html