上一篇文章中提到有時候須要設計一種內嵌的TagHelper,以下:html
<my name="yy" age="35"> <location country="China" city="Shanghai" district="PuDong"></location> </my>
location就是一個內嵌的TagHelper,咱們能夠在location裏設置與它相關的Attributes,有時候設置有多層內嵌的TagHelper。那麼怎樣設計出這樣的一個內嵌的TagHelper來呢?其實它和通常的TagHelper沒什麼的區別,你們能夠利用前面咱們介紹的來設計出它的TagHelper類及Attributes。和通常的TagHelper的主要區別是,它和父TagHelper關聯。如何創建這種關聯?這也是這章咱們須要搞清楚的。異步
經過前面章節學習,咱們知道設計的自定義TagHelper類都會繼承於抽象類TagHelper,在這個類中有二個方法:ide
//同步處理 public virtual void Process(TagHelperContext context, TagHelperOutput output); //異步處理 public virtual Task ProcessAsync(TagHelperContext context, TagHelperOutput output);
通常咱們會根據實際狀況來選擇重載哪一個方法。在TagHelper抽象類中,異步處理是調用同步處理方法。在這兩個方法中參數相同,在這裏詳細介紹第一個參數context。學習
它的類型是TagHelperContext,主要是存放TagHelper相關的信息:this
AllAttributesspa
TagHelper支持的全部Attribute集合,它是隻讀的。設計
Itemshtm
類型是IDictionary<object, object>,它是用來和其餘TagHelper進行聯繫樞紐,對象
/// <summary> /// Gets the collection of items used to communicate with other <see cref="ITagHelper"/>s. /// </summary> /// <remarks> /// This <see cref="IDictionary{object, object}"/> is copy-on-write in order to ensure items added to this /// collection are visible only to other <see cref="ITagHelper"/>s targeting child elements. /// </remarks> public IDictionary<object, object> Items { get; }
從上面的描述能夠看出,這個集合是copy-on-write,也就是說當前TagHelper在Items獲取父TagHelper中的Items信息,也能夠修改,刪除或者添加某一項,可是不會影響到父TagHelper的Items值,同時也會將修改後的Items信息傳給其子TagHelper,子TagHelper的任何修改不會影響到它。blog
在上面咱們提到,設計支持內嵌TagHelper類,關鍵是要創建父子TagHelper的聯繫,看到這裏,我想你們都應該清楚如何創建這種關聯。對了,就是利用context中Items。
主要是在TagHelper的Process方法中作如下事情。
public virtual void Process(TagHelperContext context, TagHelperOutput output) { // 從context.items獲取父TagHelper信息 // 處理自身Attributes // 將自身信息存放在context.items中 // 處理本身的子TagHelper }
更具體的例子以下:
//定義父TagHelper public class PersonTagHelper : TagHelper { public string Name { get { return Person.Name; } set { Person.Name = value; } } public int Age { get { return Person.Age; } set { Person.Age = value; } } private Person _person; private Person Person { get { return _person ?? (_person = new Person()); } set { _person = value; } } public override void Process(TagHelperContext context, TagHelperOutput output) { // 保存信息給子TagHelper使用 context.Items["Parent"] = Person; // 執行並獲取子TagHelper內容 context.GetChildContentAsync(); // 輸出html元素和啓動腳本 // 這裏會用到第二個參數output,後面會介紹到如何使用。 } } // 定義子TagHelper public class LocationTagHelper: TagHelper { public string Country { get; set; } public string City { get; set; } public string District { get; set; } public override void Process(TagHelperContext context, TagHelperOutput output) { // 獲取來自父TagHelper的信息,並保存到變量裏去 var parent = context.Items["Parent"] as Person; // 處理Attributes的設置 parent.Location.Country = Country; parent.Location.City = City; parent.Location.District = District; // 保存自身信息,便於子TagHelper使用 context.Items["Parent"] = parent.Location; // 執行並獲取子TagHelper內容 context.GetChildContentAsync(); } } // 定義了父TagHelper中對應的對象實例 // 你們能夠根據各自需求,決定是否須要定義這樣一個類型 public class Person { public string Name { get; set; } public int Age { get; set; } private Location _location; public Location Location { get { return _location ?? (_location = new Location()); } } } // 定義子TagHelper中數據類型 // 你們能夠根據各自需求,決定是否須要定義這樣一個類型 public class Location { public string Country { get; set; } public string City { get; set; } public string District { get; set; } }
對於類Person和Location的定義你們能夠根據具體狀況來決定是否須要。
這個例子只是簡單展現如何利用Items信息來構建父子TagHelper間的聯繫,你們在具體的項目開發中根據實際需求,寫出不同的代碼來,但有一點不變,就是要利用Items。