• 关于NopCommerce-Web层中的布局页


    以下内容大部分都不是原创,因为各位写手都是抄来抄去,所以我也不知道原创是谁,写这些只是为了方便自己的学习。

    首先,Nop.Web也是一个MVC Web应用程序项目,一个公有区域的展示层。它就是你实际能够运行的应用程序。它是应用程序的启动项目。

    一、概况

      nopcommerce其布局页文件分布在Nop.Web/Views/shared当中,主要涉及到五个布局文件:_Root.Head.cshtml、_Root.cshtml、_ColumnsOne.cshtml、_ColumnsTwo.cshtml、_ColumnsThree.cshtml。_ColumnsOne(Two/Three).cshtml三个布局页继承自_Root.cshtml、_Root.cshtml继承自_Root.Head.cshtml。

      所有继承_Root.Head.cshtml的页面将会使用相同的<head>标签内容,<body>体由它的子布局页来进一步细化。

      _Root.cshtml此页面替换掉_Root.Head.cshtml中@RenderBody(),大致结构如下图:

      Designer's Guide

      nopcommerc有三个不同的具体布局页:_ColumnsOne(Two/Three).cshtml,三者形式如下:

      1._ColumnsOne.cshtml

      <body>结构与_Root.cshtml一致。

      2._ColumnsTwo.cshtml

          <body>有两种:

      Designer's Guide

      Designer's Guide

      3._ColumnsThree.cshml Layout

      而到了这里,其结构就有三种:

      Designer's Guide

      Designer's Guide

      Designer's Guide

      

      也就是说_Root.Head主要管<head>中内容设置,以及全局CSS、JS文件引入;_Root.cshtml将网页主体内容<body>设计完成;_ColumnsOne(Two/Three).cshtml对_Root.cshtml变形处理。

    二 、细读                                                              

      1._Root.Head.cshtml

      顶层_Root.Head.cshtml内容如下:

     1 @using Nop.Core
     2 @using Nop.Core.Domain.Common;
     3 @using Nop.Core.Infrastructure;
     4 @{
     5     var displayMiniProfiler = CommonHelper.GetTrustLevel() >= AspNetHostingPermissionLevel.High &&
     6         EngineContext.Current.Resolve<Nop.Core.Domain.StoreInformationSettings>().DisplayMiniProfilerInPublicStore;
     7  
     8     //resources
     9     Html.AppendCssFileParts("~/Content/jquery-ui-themes/smoothness/jquery-ui-1.10.3.custom.min.css");
    10  
    11     Html.AppendScriptParts("~/Scripts/public.ajaxcart.js");
    12     Html.AppendScriptParts("~/Scripts/public.common.js");
    13     Html.AppendScriptParts("~/Scripts/jquery-migrate-1.2.1.min.js");
    14     Html.AppendScriptParts("~/Scripts/jquery-ui-1.10.3.custom.min.js");
    15     Html.AppendScriptParts("~/Scripts/jquery.validate.unobtrusive.min.js");
    16     Html.AppendScriptParts("~/Scripts/jquery.validate.min.js");
    17     Html.AppendScriptParts("~/Scripts/jquery-1.10.2.min.js");
    18  
    19     //X-UA-Compatible tag
    20     var commonSettings = EngineContext.Current.Resolve<CommonSettings>();
    21     if (commonSettings.RenderXuaCompatible)
    22     {
    23         Html.AppendHeadCustomParts(string.Format("<meta http-equiv="X-UA-Compatible" content="{0}"/>", commonSettings.XuaCompatibleValue));
    24     }
    25 }
    26 <!DOCTYPE html>
    27 <html @Html.Partial("LanguageAttributes")>
    28 <head>
    29     <title>@Html.NopTitle(true)</title>
    30     <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
    31     <meta name="description" content="@(Html.NopMetaDescription())" />
    32     <meta name="keywords" content="@(Html.NopMetaKeywords())" />
    33     <meta name="generator" content="nopCommerce" />
    34     @Html.NopHeadCustom()
    35     @*This is used so that themes can inject content into the header*@
    36     @Html.Partial("Head")
    37     @Html.Widget("head_html_tag")
    38     @Html.NopCssFiles(this.Url, ResourceLocation.Head)
    39     @Html.NopScripts(this.Url, ResourceLocation.Head)
    40     @Html.NopCanonicalUrls()
    41     @Html.Action("RssHeaderLink", "News")
    42     @Html.Action("RssHeaderLink", "Blog")
    43     @*Favicon - upload favicon.ico file to the root directory*@
    44     @Html.Action("Favicon", "Common")
    45     @if (displayMiniProfiler)
    46     {
    47         @StackExchange.Profiling.MiniProfiler.RenderIncludes()
    48     }
    49     <!--Powered by nopCommerce - http://www.nopCommerce.com-->
    50     <!--Copyright (c) 2008-2013-->
    51 </head>
    52 <body>
    53     @RenderBody()
    54     @Html.NopCssFiles(this.Url, ResourceLocation.Foot)
    55     @Html.NopScripts(this.Url, ResourceLocation.Foot)
    56 </body>
    57 </html>
    View Code


     

    1.1. Html.AppendCssFileParts() 与AppendScriptParts()

    两个方法都是nop为HtmlHelper类定义拓展方法。见名知意,AppendScriptParts附加脚本文件,AppendCssFileParts附加CSS文件:

    // private readonly Dictionary<ResourceLocation, List<string>> _cssParts;
    
     public virtual void AppendCssFileParts(ResourceLocation location, string part)     
    
        {          
    
               if (!_cssParts.ContainsKey(location))              
    
                   _cssParts.Add(location, new List<string>());
    
               if (string.IsNullOrEmpty(part))          
    
                   return;                      
    
               _cssParts[location].Insert(0, part);        
    
    }
    

    _cssParts为字典类型,根据传入的location确定键值,而字符串参数 part是CSS文件的路径。此方法最终就是将传入的CSS文件路径附加到_cssParts Dictionary当中。

    与此对应还有一个AddCssFileParts。

    public virtual void AddCssFileParts(ResourceLocation location, string part)
            {
                if (!_cssParts.ContainsKey(location))
                    _cssParts.Add(location, new List<string>());
    
                if (string.IsNullOrEmpty(part))
                    return;
    
                _cssParts[location].Add(part);
            }
    

    注意到两者的差别仅仅是给Dictionary<ResourceLocation, List<string>>添加值顺序的不同,Append在Dictionary索引为0处添加,Add在队列末尾添加。因此产生的效果是:AppendCssFileParts()调用越靠后,在界面上显示反而越靠前。大家在_Root.Head.cshtml代码中可以看到 jquery-1.7.1.min.js的引用是在最后,但是通常我们是应该将其引用位置尽量考前。

    AppendScriptParts()与AppendCssFileParts()非常相似,这里就不再贴代码说明。

    1.2 @Html.Partial("LanguageAttributes")

     就是字符串:

    @if (this.ShouldUseRtlTheme())
    {
        <text>dir="rtl"</text>
        //<text>dir="rtl" xml:lang="he" lang="he"</text>
    }
    

    ShouldUseRtlTheme()方法从当前用户的配置信息中读取其阅读方式是左到右,还是右到左,其实现依托<html>标签 的dir属性。

    1.3 @(Html.NopMetaDescription()

    NopMetaDescription方法中调用下面关键方法:

     public virtual string GenerateMetaDescription()
            {
                var metaDescription = string.Join(", ", _metaDescriptionParts.AsEnumerable().Reverse().ToArray());
                var result = !String.IsNullOrEmpty(metaDescription) ? metaDescription : _seoSettings.DefaultMetaDescription;
                return result;
            }
    

     DefaultMetaDescription是属性,从数据库中查取。

    1.4 @Html.Action("RssHeaderLink", "News")、@Html.Action("RssHeaderLink", "Blog")

     返回形如这样的字符串:<link href="xx" rel="alternate" ……>,用于RSS

    1.5 @Html.Action("Favicon", "Common")

    返回的字符串形式这样: <link rel="shortcut icon" href="XX" />,href属性默认寻找Nop.Web根目录下名字为favicon.ico文件。

    2._Root.cshtml 

     _Root.cshtml内容如下:

     1 @{
     2     Layout = "~/Views/Shared/_Root.Head.cshtml";
     3 }
     4 @Html.Widget("body_start_html_tag_after")
     5 @Html.Partial("_Notifications")
     6 @Html.Action("AdminHeaderLinks", "Common")
     7 <div class="master-wrapper-page">
     8     @Html.Action("JavaScriptDisabledWarning", "Common")
     9     <div class="master-wrapper-content">
    10         <script type="text/javascript">
    11             AjaxCart.init(false, '.header-links .cart-qty', '.header-links .wishlist-qty', '#flyout-cart');
    12         </script>
    13         @Html.Partial("Header")
    14         <div class="header-menu">
    15             @Html.Action("TopMenu", "Catalog")
    16         </div>
    17         @Html.Widget("content_before")
    18         @*ajax loading window*@
    19         <div class="ajax-loading-block-window" style="display: none">
    20             <div class="loading-image">
    21             </div>
    22         </div>
    23         <div class="master-wrapper-main">
    24             @RenderBody()
    25         </div>
    26         @Html.Widget("content_after")
    27     </div>
    28     @Html.Action("Footer", "Common")
    29 </div>
    30 @Html.Action("EuCookieLaw", "Common")
    31 @Html.Widget("body_end_html_tag_before")
    View Code


    2.1  @Html.Action("JavaScriptDisabledWarning", "Common")

    返回一个PartialView:

    @model dynamic
    <noscript>
        <div class="noscript">
            <p>
                <strong>JavaScript seems to be disabled in your browser.</strong></p>
            <p>
                You must have JavaScript enabled in your browser to utilize the functionality of
                this website.</p>
        </div>
    </noscript>
    

     其目的就是检测是否禁用JS,如果禁用就提示。

    2.2 @Html.Partial("_Notifications")

    弹出提示: 

     1 @{
     2     //success messages
     3     var successMessages = new List<string>();
     4     if (TempData[string.Format("nop.notifications.{0}", NotifyType.Success)] != null)
     5     {
     6         successMessages.AddRange(TempData[string.Format("nop.notifications.{0}", NotifyType.Success)] as IList<string>);
     7     }
     8     if (ViewData[string.Format("nop.notifications.{0}", NotifyType.Success)] != null)
     9     {
    10         successMessages.AddRange(ViewData[string.Format("nop.notifications.{0}", NotifyType.Success)] as IList<string>);
    11     }
    12 
    13 
    14     //error messages
    15     var errorMessages = new List<string>();
    16     if (TempData[string.Format("nop.notifications.{0}", NotifyType.Error)] != null)
    17     {
    18         errorMessages.AddRange(TempData[string.Format("nop.notifications.{0}", NotifyType.Error)] as IList<string>);
    19     }
    20     if (ViewData[string.Format("nop.notifications.{0}", NotifyType.Error)] != null)
    21     {
    22         errorMessages.AddRange(ViewData[string.Format("nop.notifications.{0}", NotifyType.Error)] as IList<string>);
    23     }
    24 }
    25 @foreach (var message in successMessages)
    26 {
    27     <script type="text/javascript">
    28         $(document).ready(function () {
    29             displayPopupNotification('@Html.Raw(HttpUtility.JavaScriptStringEncode(message))', 'success', false);
    30         });
    31     </script>
    32 }
    33 @foreach (var message in errorMessages)
    34 {
    35     <script type="text/javascript">
    36         $(document).ready(function () {
    37             displayPopupNotification('@Html.Raw(HttpUtility.JavaScriptStringEncode(message))', 'error', false);
    38         });
    39     </script>
    40 }
    41 <div id="dialog-notifications-success" title="@T("Common.Notification")" style="display:none;">
    42 </div>
    43 <div id="dialog-notifications-error" title="@T("Common.Error")" style="display:none;">
    44 </div>
    45 <div id="bar-notification" class="bar-notification">
    46     <span class="close" title="@T("Common.Close")">&nbsp;</span>
    47 </div>
    48 @Html.Widget("notifications")
    View Code

    通知内容通过TempData[nop.notifications.sucess]获取,注意到使用的是TempData,所以nop的通知是跨action的。

    2.3  @Html.Partial("Header")

    对应第一部分图中header,包含了头部链接、搜索框等内容。

    2.4  @Html.Action("Menu", "Common")

    菜单,对应第一部分图中的Menu,这个好理解。

    主人寄语:很详细的一篇文章,希望你读通。

       

  • 相关阅读:
    Linux-grep 命令和find 命令 (6)
    第1阶段——u-boot分析之make 100ask24x0_config指令(1)
    shell变量$(CURDIR),$0,$1,$2,$#含义解释
    ln命令详解
    快速解决设置Android 23.0以上版本对SD卡的读写权限无效的问题
    java.io.IOException: Cleartext HTTP traffic to xxx.xxx.xxx.xxx not permitted
    AndroidStudio 3.0中之后无法打开DDMS [Android Device Monitor] 问题
    解决android sdk docs帮助文档打开慢的问题
    Android Intent的使用
    约束布局ConstraintLayout详解
  • 原文地址:https://www.cnblogs.com/jingshihaisu/p/3736664.html
Copyright © 2020-2023  润新知