使用C#级联HTML标记

在使用Bootstrap编写用于ASP.NET MVC的Web应用程序的下一个过程中,我发现自己想必可以减去不可避免的HTML标签的创建。 这与扩展Html空间的用户控件无关,而是更远的地方。 急于求成,我建议您在这里(GitHub)看看,其余的,欢迎关注。

挑战赛


有一个HTML标签,其中包含名称,类,样式,属性等。 在.NET中,为了“手动”创建这种外观,假定使用TagBuilder类,并逐步用必要的元数据和公正数据填充它。

但是!

在我看来,经常使用该课程太沉闷了。 常量* .AddCssClass,* .Attributes.Add,* .MergeAttribute和* .ToString(TagRenderMode.SelfClosing)-在某些时候开始逐步惹恼他们。

这是一个标准按钮元素的示例:

<!-- HTML --> <button type="button" class="btn btn-success">Success</button> 

 // C# var tb = new TagBuilder("button"); tb.Attributes.Add("type", "button"); tb.AddCssClass("btn"); tb.AddCssClass("btn-success"); tb.SetInnerText("Success"); var htmlString = tb.ToString(TagRenderMode.Normal); 

我们在此处添加的内容是,有时HTML标签需要嵌套,这意味着您需要一个或多个* .InnerHtml和一个参数,而每个参数又应以相同的方式创建-长步逐步-很明显,您需要一些东西一些不太常规的东西。

这就是TagDecorator类的诞生方式。

我要解决的问题如下:- 简化HTML标签的创建,逐步进行并组织HTML层次结构的自然嵌套。

解决方案


链接: TagDecorator

在初始阶段,解决方案由两类组成,但随后又添加了另一类:

TagDecorator是主要的工作类,负责将纯文本转换为表示标记的类(TagWrapper),可以在其上附加扩展名。 在现有示例中,既有通用函数AddAttribute,AddCss,又有私有函数AddType,AddName,AddId-创建特定的属性。

TagWrapper是表示标签的类。 它被创建为在可能的情况下完全脱离TagBuilder,并且IntelliSense中的新扩展名并未与TagBuilder类的属性混淆。

标签 -分隔开始/结束标签所需的类,以实现在RazorView中使用的框架HTML块

 @using(Html.SuchExtension) { //... }. 

例子


在指示的按钮示例中,使用TagDecorator的优势并不明显:

 var htmlString = "button".ToTag() .AddType("button") .AddCss(new[] {"btn", "btn-success"}) .SetText("Success") .ToString(); 

但是现在以Bootstrap卡为例-一切已经变得令人赏心悦目:

使用TagBuilder

 var divMain = new TagBuilder("div"); divMain.AddCssClass("card"); divMain.Attributes.Add("style", "width: 18rem;"); var img = new TagBuilder("img"); img.AddCssClass("card-img-top"); img.Attributes.Add("src", "..."); img.Attributes.Add("alt", "Card image cap"); var divBody = new TagBuilder("div"); divBody.AddCssClass("card-body"); var h = new TagBuilder("h5"); h.AddCssClass("card-title"); h.SetInnerText("Card title"); var p = new TagBuilder("p"); p.AddCssClass("card-text"); p.SetInnerText("Some quick example text to build on the card title and make up the bulk of the card's content."); var a = new TagBuilder("a"); a.Attributes.Add("href", "#"); a.AddCssClass("btn"); a.AddCssClass("btn-primary"); a.SetInnerText("Go somewhere"); divBody.InnerHtml += h.ToString(TagRenderMode.Normal); divBody.InnerHtml += p.ToString(TagRenderMode.Normal); divBody.InnerHtml += a.ToString(TagRenderMode.Normal); divMain.InnerHtml += img.ToString(TagRenderMode.Normal); divMain.InnerHtml += divBody.ToString(TagRenderMode.Normal); return divMain.ToString(TagRenderMode.Normal); 

带有TagDecorator的版本
 var htmlString = "div".ToTag() .AddCss("card") .AddAttribute("style", "width: 18rem;") .InnerHtml(new [] { "img".ToTag() .AddCss("card-img-top") .AddAttributes(new[] {new[] {"src", "..."}, new[] {"alt", "Card image cap"}}), "div".ToTag() .AddCss("card-body") .InnerHtml(new [] { "h5".ToTag().AddCss("card-title").SetText("Card title"), "p".ToTag().AddCss("card-text").SetText("Some quick example text to build on the card title and make up the bulk of the card's content."), "a".ToTag().AddCss(new[] {"btn", "btn-primary"}).AddAttribute("href", "#").SetText("Go somewhere") }) }).ToString(); 

结果


缺点


我认为主要的观点是,级联实现有时会将代码向右移动,通常会超出开发人员的视野,并且层次结构越复杂,则代码越强大

优点


+代码行-减少。 在最简单的元素中,在复杂的HTML树中大约有1-2行的增益-如果使用TagBuilder,按类推,大约有1/3行。

+可见性-您可以清楚地看到嵌套的位置和种类。 一切都是层次直观的,易于理解。

+可扩展性-需要一些特定的情况/属性-只需添加扩展名即可。 需要条件检查-添加扩展。

可能的改进


最初,我考虑过基于这些类创建完全专用的标签,这些标签仅允许工具提示中的某些扩展-例如,删除button标签中的AddReference扩展工具提示,但随后为了通用起见放弃了这些计划。 但总的来说,这种解决方案现在对我的项目有很大帮助。

还应该创建一个NuGet程序包,但是由于时间不足-一切都被推迟了。

Source: https://habr.com/ru/post/zh-CN416459/


All Articles