【NetCore学习笔记之TagHelper】自定义自己的TagHelper

自打Netcore推出以来,很多人是紧追不舍,关注度颇高,一时间让它成为了asp.net中的一等公民。我也是其中一份子,顶多算是一个伪粉丝吧,因为关注不太多,不够深。

今天,主要记录的学习笔记是:如何自定义自己的Taghelper。话不多说,直入正题:

1、定义接口

 public interface ICountryService
    {
        IEnumerable<CountryModel> GetAll();
    }

2、定义接口实现类

 public class CountryService : ICountryService
    {
        private static IEnumerable<CountryModel> CountryList = new List<CountryModel>()
        {
            new CountryModel() { Id=1,enName="China",CnName="中国",Code="China"},
            new CountryModel() { Id=2,enName="Japan",CnName="日本",Code="Japan"},
            new CountryModel() { Id=3,enName="America",CnName="美国",Code="America"},
        };
        public IEnumerable<CountryModel> GetAll()
        {
            return CountryList;
        }
    }

3、注入

  对于注入,多说几句。在.net core中,有几种常见注入方式:分别为(个人理解,不对的请大牛斧正):

  AddTransient: 每次请求ICountryService,就会生成一个对象;

  AddSingleton: 顾名思义,单例模式;贯穿整个application的生命周期,从Start--->End;

  AddScoped:可以理解为贯穿当前请求的整个生命周期。怎么理解呢,就是说当你第一次请求ICountryService的一个对象;在该请求的另外一个环节中,如果用到了ICountryService的其他逻辑,那么同样会共用第一次生成的对象。直到此次请求的生命周期结束。我个人认为,相当于生命周期内部的单例模式;

  

public void ConfigureServices(IServiceCollection services)
{
    // the others

    services.AddTransient<ICountryService, CountryService>();

}

4、自定义自己的Taghelper方法

 // 自定义Taghelper类,主要的是要继承TagHelper,位于命名空间Microsoft.AspNetCore.Razor.TagHelpers下
 public class CountryListTagHelper : TagHelper
    {
        private readonly ICountryService _countryService;

        public string SelectedValue { get; set; } // 自定义的属性,在后续中会用到
        public CountryListTagHelper(ICountryService countryService)
        {
            _countryService = countryService;
        }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            output.TagName = "select";
            output.Content.Clear();

            foreach (var item in _countryService.GetAll())
            {
                var seleted = "";
                if (SelectedValue != null && SelectedValue.Equals(item.Code, StringComparison.CurrentCultureIgnoreCase))
                {
                    seleted = " selected=\"selected\"";
                }

                var listItem = $"<option value=\"{item.Code}\"{seleted}>{item.CnName}-{item.enName}</option>";
                output.Content.AppendHtml(listItem);

            }

            //base.Process(context, output);
        }
    }

因为需要继承TagHelper,所以需要引入以下依赖包(如果用VS2015工具开发,会提示会让你安装什么什么依赖的):

  "Microsoft.AspNetCore.Razor.Runtime": "1.0.0",
   "Microsoft.AspNetCore.Mvc.TagHelpers": "1.0.0"

其实,这里只是使用到了同步方法,还有一个异步方法,具体定义和描述如下:
namespace Microsoft.AspNetCore.Razor.TagHelpers
{
  /// <summary>Class used to filter matching HTML elements.</summary>
  public abstract class TagHelper : ITagHelper
  {
    protected TagHelper();
    /// <inheritdoc />
    public virtual void Init(TagHelperContext context);
    /// <summary>
    /// Synchronously executes the <see cref="T:Microsoft.AspNetCore.Razor.TagHelpers.TagHelper" /> with the given <paramref name="context" /> and
    /// <paramref name="output" />.
    /// </summary>
    /// <param name="context">Contains information associated with the current HTML tag.</param>
    /// <param name="output">A stateful HTML element used to generate an HTML tag.</param>
    public virtual void Process(TagHelperContext context, TagHelperOutput output);
    /// <summary>
    /// Asynchronously executes the <see cref="T:Microsoft.AspNetCore.Razor.TagHelpers.TagHelper" /> with the given <paramref name="context" /> and
    /// <paramref name="output" />.
    /// </summary>
    /// <param name="context">Contains information associated with the current HTML tag.</param>
    /// <param name="output">A stateful HTML element used to generate an HTML tag.</param>
    /// <returns>A <see cref="T:System.Threading.Tasks.Task" /> that on completion updates the <paramref name="output" />.</returns>
    /// <remarks>By default this calls into <see cref="M:Microsoft.AspNetCore.Razor.TagHelpers.TagHelper.Process(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext,Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput)" />.</remarks>
    /// .
    public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output);
    /// <inheritdoc />
    /// <remarks>Default order is <c>0</c>.</remarks>
    public virtual int Order { get; }
  }
}

  轮子到此就算是造好了,那就需要要检测一下是否能跑吧。

5、应用检测

我这里就把这个引用放到了单个view页面中了,(以下三种方式,任选其一即可)

// 格式:@addTagHelper typeName,AssemblyName
// 方式一,程序集下所有的Taghelper
@addTagHelper *,TodoList.Project
// 方式二,明确指定路径
@addTagHelper "TodoList.Project.Extensions.CountryListTagHelper,TodoList.Project"

// 方式三,模糊匹配
@addTagHelper "TodoList.Project.Extensions.CountryList*,TodoList.Project"

标签引入方式为:

<country-list selected-value="China"></country-list>

效果图如下:

生成的html代码为:

<select><option value="China" selected="selected">中国-China</option><option value="Japan">日本-Japan</option><option value="America">美国-America</option></select>

其实这里涉及到了两个地方,一个是创建项目时,自带的_ViewImports.cshtml,这个文件是干嘛的呢?个人理解是view中需要导入的一些命名空间之类的。而且是全局使用的。

如果你要是单独一个view使用,那么就在对应的view页面中增加即可。

对于标签的命名规则:

  大概是:如果有多个大写字母组成的(比如CountryList),那么会把大写全部转换为小写,然后分割单词(比如:CountryList--->country-list);

  如果是单个单词,则直接转小写;(比如EmailTagHelper ---> email);

如果,你想自己指定html标签属性,可以在TagHelper上增加一个属性标签:

    [HtmlTargetElement("country-lists")]
    public class CountryListTagHelper : TagHelper

使用的时候,就是<country-lists selected-value="China"></country-lists>

6、后记

主要是有一些疑问,我大概翻了一下源码,也没找到对于自定义的Taghelper,在前面页面中使用的命名规则是什么样子的。就断断续续看到过一些备注上的示例。这让我有点不爽。(谁找到了,麻烦告诉一下在哪里)

其实,也有一些自带的Taghelper,比如:

参考资料:

 https://docs.asp.net/en/latest/mvc/views/tag-helpers/intro.html

http://www.cnblogs.com/TomXu/p/4496480.html
时间: 2024-09-30 02:07:43

【NetCore学习笔记之TagHelper】自定义自己的TagHelper的相关文章

Android学习笔记18:自定义Seekbar拖动条式样

Android学习笔记18:自定义Seekbar拖动条式样

[原创]java WEB学习笔记45:自定义HttpFilter类,理解多个Filter 代码的执行顺序,Filterdemo:禁用浏览器缓存的Filter,字符编码的Filter,检查用户是否登陆过的Filter

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

Android(java)学习笔记204:自定义SmartImageView(继承自ImageView,扩展功能为自动获取网络路径图片)

1.有时候Android系统配置的UI控件,不能满足我们的需求,Android开发做到了一定程度,多少都会用到自定义控件,一方面是更加灵活,另一方面在大数据量的情况下自定义控件的效率比写布局文件更高. 2.下面我们是自定义一个SmartImageView继承自ImageView,扩展了ImageView的功能:     步骤: • 新建一个SmartImageView类,让继承自ImageView(放置特定的包下): • 实现SmartImageView类下的构造方法,最好全部实现,这个不容易出

ArcGIS API for JavaScript 4.2学习笔记[16] 弹窗自定义功能按钮及为要素自定义按钮(第五章完结)

这节对Popups这一章的最后两个例子进行介绍和解析. 第一个[Popup Actions]介绍了弹窗中如何自定义工具按钮(名为actions),以PopupTemplate+FeatureLayer的形式测量要素的长度为例子进行介绍. 第二个[Custom popup actions per feature]则是上一个的升级,如果说上一个例子的功能是写死的,那么这个例子就把这个功能写活了.什么意思呢?上个例子的测距仅仅能测距,没有什么别的特别的.而这个例子以啤酒店的分布(点要素图层)为例,在自

第三方类库学习笔记:CustomShapeImageView 自定义形状的ImageView

一个两年前出来的第三方类库,具有不限于圆形ImageView的多种形状ImageView,项目开发必备 github下载地址:https://github.com/MostafaGazar/CustomShapeImageView 1.首先源码中有一个第三方类库 :library 先要把Library导入到项目中, 不会的可以看下导入方法:关于Eclipse 和 IDEA 导入library库文件 的步骤 2.源码中res文件夹下有一个raw文件夹 复制到自己的项目中(选择性复制,是一些特殊的图

Haskell学习笔记二:自定义类型

内容提要: 代数数据类型 - Algebraic Data Types: 自定义数据类型 - data关键字:值构造器:类型变量与类型构造器: 记录(Record)语法 - 简化自定义数据类型的一种语法糖: 一个完整的例子 - PurchaseOrder定义和简单计算.单元测试: 代数数据类型(Algebraic Data Types) 为什么Haskell的数据类型会有代数数据类型这个名字?回想我们初中时代,初次学习代数的情况,印象最深刻就是x,y,z代替了具体的数字,引入方程式的概念,对 解

CSS学习笔记三:自定义单选框,复选框,开关

一点一点学习CCS,这次学习了如何自定义单选框,复选框以及开关. 一.单选框 1.先写好body里面的样式,先写几个框 1 <body> 2 <div class="radio-1"> 3 <input type="radio" name="radio-1" id="radio-1-1"> 4 <label for="radio-1-1"></label

struts2学习笔记之十三:自定义过滤器

Struts2的拦截器 1.Struts2的拦截器只能拦截Action,拦截器是AOP的一种思路,可以使我们的系统架构 更松散(耦合度低),可以插拔,容易互换,代码不改变的情况下很容易满足客户需求 其实体现了OCP 2.如何实现拦截器?(整个拦截器体现了责任链模式,Filter也体现了责任链模式) * 继承AbstractInterceptor(体现了缺省适配器模式,建议使用该模式) * 实现Interceptor 3.如果自定了拦截器,缺省拦截器会失效,必须显示引用Struts2默认的拦截器

C#学习笔记-Windows窗体自定义初始位置

根据屏幕大小定义初始位置: (这个不是难,但是最近常常忘记,记着方便查看.) 1 //获取当前屏幕的长和宽 2 int ScreenX = Screen.PrimaryScreen.Bounds.Width; 3 int ScreenY = Screen.PrimaryScreen.Bounds.Height; 4 5 //注意记得让窗体的StartPosition的属性改为Manual,这样才能自定义 6 //减去的是窗体的长度和宽度的一半,这样才能让窗体居中显示 7 int StartPos