【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,都在命名空間Microsoft.AspNetCore.Mvc.TagHelpers下,比如:FormTagHelper、InputTagHelper、selectTagHelper、LabelTagHelper、validationTagHelper等;

比如selectTagHelper,可以這么玩:

SelectListItem[] items =
  {
     new SelectListItem() {Text = "男♂", Value = "1"},
     new SelectListItem() {Text = "女♀", Value = "0"}
  };

ViewBag.gender
= items;
 <select asp-for="Sex" id="inputSex" asp-items="@ViewBag.gender">
     <option selected="selected" value="">Choose gender</option>
 </select>

 

擴展:

對於系統自帶的一些TagHelper的使用小知識點記錄 

  • AnchorTagHelper
/// <summary>
  /// <see cref="T:Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper" /> implementation targeting &lt;a&gt; elements.
  /// </summary>
  [HtmlTargetElement("a", Attributes = "asp-action")]
  [HtmlTargetElement("a", Attributes = "asp-controller")]
  [HtmlTargetElement("a", Attributes = "asp-area")]
  [HtmlTargetElement("a", Attributes = "asp-fragment")]
  [HtmlTargetElement("a", Attributes = "asp-host")] // 
  [HtmlTargetElement("a", Attributes = "asp-protocol")] // The protocol for the URL, such as "http" or "https".
[HtmlTargetElement("a", Attributes = "asp-route")] 
[HtmlTargetElement(
"a", Attributes = "asp-all-route-data")]
[HtmlTargetElement(
"a", Attributes = "asp-route-*")]
public class AnchorTagHelper : TagHelper

使用方法:跳轉到指定ID的詳情頁面,並且是https方式

<a asp-action="Edit" asp-protocol="https" asp-controller="Todo" asp-route-id="@item.Id">@item.Title</a>

需要注意的是asp-route-*, 可以匹配路由規則中的其他參數

 /// <summary>Additional parameters for the route.</summary>
    [HtmlAttributeName("asp-all-route-data", DictionaryAttributePrefix = "asp-route-")]
    public IDictionary<string, string> RouteValues { get; set; }

 

參考資料:

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

http://www.cnblogs.com/TomXu/p/4496480.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM