• 独立使用Asp.net Core 的razor模板 (一):Razor引擎的一些细节


        由于最近需要写一些界面稍微好看点的Winform程序,如果用原生控件,,想要达到好看的程度,需要花费比较大的功夫,因为之前使用过CefSharp,因此发觉如果是使用CEF+Html的方式,界面可以相对容易做的精致一点(其实就是设计完之后,找个前端人员切切图),但是,使用CEF+Html有个弊端就是,正常的软件,Header跟Footer大体是通用的,包括一些通用的js/css的引用以及菜单栏等等,,如果直接用html,有个问题就在于,,每个界面都要复制一遍,如果万一发生修改,每个页面又要来一次,或许都这里有朋友会说:"那可以使用vue或者ng的模板啊",,实际情况是,,会用的人不多,但是会用jq的人大把.

         由于服务器端有Razor模板,可以很方便的使用Layout以及各种自己封装的View,但实际情况下,如果单独把Razor拿出来,实际上是只有将模板string+model解析成新的string的功能而已,因此,想要独立的使用Razor就需要为独立的Razor引擎补充一些功能,

    首先需要补充的就是Layout功能

     开始动工之前,我们先来了解一下一些功能对应到Razor中,是怎么个实现方式的:

    1.先来看一段简单的cshtml文件以及生成后的类:

       _Layout.cshtml

       

     1 <html>
     2 <head>
     3     <title></title>
     4 </head>
     5 <body>
     6     
     7     
     8 @RenderBody()
     9 
    10 @RenderSection("test",false)
    11     
    12 </body>
    13 </html>
    View Code

       Index.cshtml

     1 @{
     2     Layout = "_Layout.cshtml";
     3 }
     4 
     5 <p>sdfsdfsdfs</p>
     6 
     7 
     8 @section test{
     9     <p>ddddddddd</p>
    10 }
    View Code

       Index.cshtml生成后的代码:

     1 #pragma warning disable 1591
     2 namespace TEst
     3 {
     4 #line hidden
     5     using System;
     6     using System.Threading.Tasks;
     7     public class TextFile1 : WindowsFormsApp2.RazorViewBase<WindowsFormsApp2.Model>
     8     {
     9 
    10 #pragma warning disable 1998
    11         public async override global::System.Threading.Tasks.Task ExecuteAsync()
    12         {
    13             WriteLiteral("
    
    ");
    14             WriteLiteral("
    ");
    15 #line 5 "TextFile1.cshtml"
    16 
    17             Layout = "sdfsdfsdfsf";
    18 
    19 #line default
    20 #line hidden
    21             WriteLiteral("
    <html>
    <head>
        <title></title>
    </head>
    <body>
    ");
    22             DefineSection("ui", async () =>
    23             {
    24                 WriteLiteral("
        ");
    25 #line 15 "TextFile1.cshtml"
    26                 Write(Model.A1);
    27 
    28 #line default
    29 #line hidden
    30                 WriteLiteral(";
        ");
    31 #line 16 "TextFile1.cshtml"
    32                 Write(Model.A1?.StartsWith("sfdsfdf"));
    33 
    34 #line default
    35 #line hidden
    36                 WriteLiteral("
            <p></p>
        ");
    37             }
    38             );
    39             WriteLiteral("</body>
    </html>");
    40         }
    41 #pragma warning restore 1998
    42     }
    43 }
    44 #pragma warning restore 1591
    View Code

    1.关于基类,Razor引擎可以设置本次生成的类的基类,并且,要求基类中需要实现几个函数,已供生成的子类调用

    2.@section : 如果使用section关键字,编译后,其实是调用基类的DefineSection(string name, Func<Task> act)函数,

       如:在Layout 中,使用 Html.RenderSesction 函数输出

        那么在引用该Layout的页面中,如Index.csthml中,使用

       

    1 @section header{
    2     sdfsdfsdfsdfs
    3      //TODO:其他需要输出在头部的标签
    4 }

         对应到实际生成的代码,其实是这样的

     

     1 DefineSection("header", async () =>
     2             {
     3                 WriteLiteral("
        ");
     4 #line 15 "TextFile1.cshtml"
     5                 Write(Model.A1);
     6 
     7 #line default
     8 #line hidden
     9                 WriteLiteral(";
        ");
    10 #line 16 "TextFile1.cshtml"
    11                 Write(Model.A1?.StartsWith("sfdsfdf"));
    12 
    13 #line default
    14 #line hidden
    15                 WriteLiteral("
            <p></p>
        ");
    16             }
    17             )

         由生成的代码可以看到 ,@section 段的使用,需要基类实现 DefineSection(string name, Func<Task> act) 函数,并且将传入的函数存起来,等待Html.RenderSesction 触发时调用

    3.RenderBody,该函数其实是直接把Index.cshtml中,非@section的部分直接输出,由ExecuteAsync函数开始,所有的WriteLiteral的结果总和,因为@section部分已经是通过DefineSection定义了,所以直接输出其他结果并不会干扰到

    4.WriteLiteral和Write: WriteLiteral 直接输原始数据,Write除非是输出HtmlString,否则需要转码

    5.ExecuteAsync函数:Razor其实上是把cshtml转成对ExecuteAsync函数的内容

    6.VS 的IDE支持,,由于.net core 3.0还未出正式版.所以创建的项目为.net 4.5的,而引用的又是asp.net core 的Razor,所以在IDE支持上会有一点点的小区别:

       因此为了省的IDE报太多的错误,需要在基类中,添加几个用于糊弄IDE的函数和属性:

       

    public HttpContextFake Context { set; get; }  //返回自己模拟的一个HttpContext的类,
       protected virtual void DefineSection(string name, Action act)  //函数签名略微不同
       public virtual void Execute() //IDE认的就是这个函数,不存在会报错,但没有实际用途
       
    
       [Browsable(false),Obsolete]
       public class HttpContextFake
       {
          public System.Web.HttpApplication ApplicationInstance { get; }
        }

    顺带附上Razor+NaneUI的项目的地址: https://gitee.com/kugar/Kugar.UI.RazorUI

    以上是Razor一些小的细节,,下篇文章就开始来说怎么创建一个支持Layout的独立Razor了

  • 相关阅读:
    CSS定位属性position相关介绍
    JavaScript 预解析机制
    使用 python 实现π的计算
    turtle库的学习
    关于使用MVVM模式在WPF的DataGrid控件中实现ComboBox编辑列
    关于wpf窗体中Allowtransparent和WindowsFormsHost的纠纷
    关于WPF中ItemsControl系列控件中Item不能继承父级的DataContext的解决办法
    Python简史
    敏捷开发原则
    线程池
  • 原文地址:https://www.cnblogs.com/kugar/p/10527782.html
Copyright © 2020-2023  润新知