咱們在.net core中還使用了ViewComponent方式生成控件。ViewComponent也是asp.net core的新特性,是對頁面部分的渲染,之前PartialView的功能,可使用ViewComponent來實現。 html
View Component包含2個部分,一個是類(繼承於ViewComponent),和它返回的結果Razor視圖(和普通的View視圖同樣)。 jquery
咱們仍是來看一下以側邊菜單控件爲例子,怎麼建立一個ViewComponent。側邊菜單控件以下圖: json
控件的主要邏輯是按照用戶和應用程序代碼,獲取全部已經按照父子結構組織的菜單,傳送到頁面展現。 app
上面已經提到,View Component包含2個部分,一個是類,這個類也繼承於ViewComponent類。子控件最主要的是重寫ViewComponent類的Invoke/InvokeAsync方法: 框架
1 public class SideMenuViewComponent : ViewComponent 2 { 3 private IMenuAppService service; 4 public SideMenuViewComponent(IMenuAppService service) 5 { 6 this.service = service; 7 } 8 9 public IViewComponentResult Invoke(string appCode, UserInfo userInfo) 10 { 11 IEnumerable<MenuDto> menuItems = this.service.GetHierarchy(appCode, userInfo); 12 13 return View("SideMenu", menuItems); 14 } 15 }
再來看ViewComponent的第二部分,就是Razor視圖,這裏是SideMenu.cshtml: asp.net
1 @using MicroStrutLibrary.Presentation.Web.Controls 2 @using MicroStrutLibrary.AppService.Portal 3 @using Microsoft.AspNetCore.Html 4 5 @model IEnumerable<MenuDto> 6 @{ 7 var controlId = System.Guid.NewGuid().ToString("N"); 8 } 9 10 @functions 11 { 12 public IHtmlContent RenderChildren(IEnumerable<MenuDto> menuItems) 13 { 14 string result = "<ul class=\"submenu\" style=\"display: none;\">"; 15 16 foreach (MenuDto itemInfo in menuItems) 17 { 18 var url = Url.Content(string.IsNullOrWhiteSpace(itemInfo.Url) ? "#" : itemInfo.Url); 19 var icon = string.IsNullOrWhiteSpace(itemInfo.IconClass) ? "fa fa-list-ul" : itemInfo.IconClass; 20 var leaf = (itemInfo.IsLeaf && (itemInfo.Children == null || itemInfo.Children.Count() < 1)); 21 22 result += "<li>"; 23 result += $"<a href=\"{Html.Raw(url)}\" target=\"{itemInfo.Target}\" title=\"{itemInfo.MenuDesc}\" data-feature=\"{itemInfo.WinFeature}\" data-leaf=\"{leaf.ToString().ToLower()}\"><i class=\"${Html.Raw(icon)}\"></i><span>{itemInfo.MenuName}</span></a>"; 24 if (!leaf) 25 { 26 result += RenderChildren(itemInfo.Children).ToString(); 27 } 28 } 29 30 result += "</ul>"; 31 return new HtmlString(result); 32 } 33 } 34 <div id="@(controlId)" class="jquery-accordion-menu red"> 35 <div class="jquery-accordion-menu-header"> 36 </div> 37 <ul> 38 @foreach (MenuDto itemInfo in Model) 39 { 40 var url = Url.Content(string.IsNullOrWhiteSpace(itemInfo.Url) ? "#" : itemInfo.Url); 41 var icon = string.IsNullOrWhiteSpace(itemInfo.IconClass) ? "fa fa-list-ul" : itemInfo.IconClass; 42 var leaf = (itemInfo.IsLeaf && (itemInfo.Children == null || itemInfo.Children.Count() < 1)); 43 44 <li> 45 <a href="@Html.Raw(url)" target="@itemInfo.Target" title="@itemInfo.MenuDesc" data-feature="@itemInfo.WinFeature" data-leaf="@(leaf.ToString().ToLower())"> 46 <i class="@Html.Raw(icon)"></i> 47 <span>@itemInfo.MenuName</span> 48 </a> 49 @if (!leaf) 50 { 51 @RenderChildren(itemInfo.Children) 52 } 53 </li> 54 } 55 </ul> 56 <div class="jquery-accordion-menu-footer"> 57 </div> 58 </div> 59 <script> 60 require(['jquery', 'accordionmenu'], function ($) { 61 var $sidebar = $("#@(controlId)"); 62 63 $sidebar.jqueryAccordionMenu(); 64 65 $("a", $sidebar).click(function (e) { 66 var $this = $(this); 67 68 if (!$this.data("leaf")) { 69 e.preventDefault(); 70 } else { 71 var feature = $this.data("feature"); 72 73 if (feature) { 74 e.preventDefault(); 75 window.open($this.attr("href"), $this.attr("target"), feature); 76 } 77 } 78 }); 79 $("li", $sidebar).click(function () { 80 $("li.active", $sidebar).removeClass("active"); 81 $(this).addClass("active"); 82 }); 83 }); 84 </script>
Cshtml中,咱們用到了@functions的寫法,其實就是至關於在cshtml中編寫cs的方法,通常這個方法要求返回的是IHtmlContent。ide
進階:資源性視圖的應用 ui
按照以往的慣例,咱們依舊還一個進階,說明下ViewComponent中的cshtml做爲嵌入的資源該如何寫。 this
其實作法和TagHelper是同樣的。首先是嵌入式資源方式,須要在project.json中按照以下方式編寫: url
"buildOptions": {
"embed": [ "Components/**/*.cshtml", "TagHelpers/**/*.cshtml" ]
}
而後再寫一個擴展方法,同上個文檔的EmbeddedFileServiceCollectionExtensions,最後是在Startup.cs中使用這個擴展方法。
由於咱們的ViewComponet和TagHelper都在同一個WebControls項目中,所以進階部分的代碼根本不須要再寫了。這裏再重複說明的緣由是,在沒有寫過上述代碼的狀況下,如何將ViewComponent的Cshtml做爲嵌入的資源。