Javascript模块化,基于服务器的MVC和业务现实


32

我知道这是一个非常广泛的问题,但是我已经分别处理了该问题的各个方面,并且正在努力将所有概念和技术结合在一起。

我想指定答案应包括以下技术:

  • C#
  • 带剃刀的MVC 3
  • 带有jQuery的Javascript

如果这些内容有助于回答以下问题,则欢迎将其视为超越建议的建议(例如Backbone.jsEntity Framework等):

使用上面列出的技术,在组织代码和逻辑,同时保持可伸缩性和创建丰富,快速,干净的UI的能力方面,什么是最佳策略?

理想情况下,应将重点放在部署在企业/企业环境中的解决方案上。请注意,上面的技术列表不会更改,因此请不要提供“您应该使用xxx而不是现在使用的yyy ”的解决方案。

背景

我每天都使用jQuery,已经采用ASP.NET的MVC,并且已经使用C#很长时间了。因此,您可以假设这些技术的中高级知识来提出解决方案。

我将问题分成较小的部分,以使其更易于回答:

1.项目结构

鉴于我正在使用ASP.NET MVC(在Visual Studio 2010中),我想要一个目录结构解决方案,该解决方案可以接受这种类型的应用程序的主要布局。我猜想像早午餐一样,但是每个文件夹将包含什么以及它如何与应用程序的其他区域一起工作的更多细节。

2.数据访问

我想使用一种API类型的结构来尽可能地模块化我的数据访问。你可以假设很多POCO对象(的UserUserGroupCustomerOrderHeaderOrderDetails,等),但也会有一些复杂的报表需要数据密集型的SQL和精心UI渲染。 EF + LINQ对于前者而言非常出色,但对于后者则不那么理想。在没有过于复杂或过于简单的情况下,我找不到适合两种情况的东西。

3.客户端代码组织和UI渲染

像大多数开发人员最先使用jQuery一样,我陷入了将代码混在一起的陷阱,但是很快发现它堆积并变得丑陋。尽管从那时起我就突飞猛进,但我仍在努力使代码模块化以及在不重复代码的情况下使用UI的各个部分。

举例来说,我可能会编写的典型代码看起来像这样,我评论了困扰我的东西(请注意,此后我已更改为使用延迟的AJAX调用,并从DOM操作中分离了实际的数据请求):

$('#doSomethingDangerous').click(function () {
    // maybe confirm something first
    if (confirm('Are you sure you want to do this?')) {   

        // show a spinner?  something global would be preferred so I don't have to repeat this on every page 
        $('#loading').show();  

        // maybe the page should notify the user of what's going on in addition to the dialog?
        $('#results').show().html('<h2>Please wait, this may take a while...</h2>');  

        $.ajax({
            url: 'blah/DoDangerousThing',
            success: function (data) {                     
                // The results will be loaded to the DOM obviously, is there a better way to pull this type of specific code out of the data access calls?
                $('#results').empty();
                $('#results').append('<b>' + data.length + '</b> users were affected by this dangerous activity');
                $('#results').append('<ul>');

                // I've recently started to use jQuery templates for this sort of logic, is that the way to go?
                $(data).each(function (i, user) {
                    $('#results').append('<li>' + user.Username + '</li>');
                });                    
                $('#results').append('</ul>');

                // Need to hide the spinner, again would prefer to have this done elsewhere
                $('#loading').hide();
            }
        });
    }
});

一般的问题

  • 客户端MVC与服务器MVC?我的项目已经是服务器端MVC结构,因此仍然需要Backbone.js提供的客户端MVC吗?
  • 是否应该为每个对象创建Javascript文件(如OrderHeader.js),然后在构建过程中将其缩小/合并?还是应该只存在一个Order.js具有逻辑的OrderHeader, OrderDetails, Reports等等?
  • 如何处理复杂的查询?现在,我的主要理论是/Reports/Orders-By-Date/类似的东西,我使用了一个自定义SQL查询,该查询将自定义数据集(或ViewModel)呈现到Razor View。但是分页,排序等呢?这样做是在客户端还是在服务器端更好?(假设更大的数据集-2至3秒的SQL查询)
  • 我已经阅读了Microsoft的Project Silk。这是个好方法吗?与Backbone.js或其他产品相比如何?
  • 我非常习惯于N层体系结构,这些概念在某种程度上将其排除在外了吗?看起来MVC就像是过去的前端或顶层中的一堆微型N层部分。

同样,您的答案越具体,它们就会越好。 我已经阅读了很多高级文档和示例,我试图更好地理解将其转换为实际的示例


2
您在这个问题上花了很多力气,但是对我来说,这似乎并不是一个Stackoverflow问题。也许程序员stackexchange更合适。
Pointy

3
我不同意这是一个有趣的话题,但是Stackoverflow应该是关于客观问题的。这样的问题基本上是“可能征求意见,辩论,辩论,民意调查或扩展讨论”问题的发源人。
Pointy

8
有一群人一直在计划最大规模的计划,而我却悄悄关闭了他们的业务,因为他们花了太长时间计划了从未发生的事情。
杰森·塞布林

1
我同意@Pointy,它属于程序员堆栈。您的问题很有趣,我会一直关注,因为我一直在寻求建议。但这不是一个客观问题,只会在优先辩论中结束。与往常一样,最适合您的情况是什么...我们都不了解您的网络结构,客户端数量或流量统计信息或构建过程...所以问题太模糊了...我所知道的是避免丝绸。;)
one.beat.consumer 2011年

1
这个问题恰好符合“过于广泛”的定义,因此符合“不是一个真正的问题”。如果有的话,应将单个问题作为带有轻微背景的单个问题(太多,人们会标记为“不是真正的问题”)。但是,请小心,您要问的许多单个问题可能会被标记为“不具有建设性”,因此,我对您如何提出这些问题要小心。
casperOne 2011年

Answers:


10

我的朋友TerryR,您和我应该喝一杯。我们有一些类似的问题。

1.项目结构:我同意Eduardo的观点,即MVC应用程序中的文件夹结构有待改进。您具有标准的Controllers,Models和Views文件夹。但是随后,Views文件夹被分解为每个Controller的不同文件夹,再加上Shared文件夹。每个View / ControllerName或Views / Shared都可以细分为EditorTemplates和DisplayTemplates。但是,它可以让您决定如何组织Models文件夹(可以使用或不使用子文件夹和其他名称空间声明)。

上帝禁止您使用Areas,它们会为每个区域复制Controllers,Models和Views文件夹结构。

/Areas
    /Area1Name
        /Controllers
            FirstController.cs
            SecondController.cs
            ThirdController.cs
        /Models
            (can organize all in here or in separate folders / namespaces)
        /Views
            /First
                /DisplayTemplates
                    WidgetAbc.cshtml <-- to be used by views in Views/First
                /EditorTemplates
                    WidgetAbc.cshtml <-- to be used by views in Views/First
                PartialViewAbc.cshtml <-- to be used by FirstController
            /Second
                PartialViewDef.cshtml <-- to be used by SecondController
            /Third
                PartialViewMno.cshtml <-- to be used by ThirdController
            /Shared
                /DisplayTemplates
                    WidgetXyz.cshtml <-- to be used by any view in Area1
                /EditorTemplates
                    WidgetXyz.cshtml <-- to be used by any view in Area1
                PartialViewXyz.cshtml <-- to be used anywhere in Area1
            _ViewStart.cshtml <-- area needs its own _ViewStart.cshtml
            Web.config <-- put custom HTML Helper namespaces in here
        Area1NameRegistration.cs <-- define routes for area1 here
    /Area2Name
        /Controllers
        /Models
        /Views
        Area2NameRegistration.cs <-- define routes for area2 here

/Controllers
    AccountController.cs
    HomeController.cs
/Models
/Views
    /Account
        /DisplayTemplates
            WidgetGhi.cshtml <-- to be used views in Views/Account
        /EditorTemplates
            WidgetGhi.cshtml <-- to be used views in Views/Account
        PartialViewGhi.cshtml <-- to be used by AccountController
    /Home
        (same pattern as Account, views & templates are controller-specific)
    /Shared
        /DisplayTemplates 
            EmailAddress.cshtml <-- to be used by any view in any area
            Time.cshtml <-- to be used by any view in any area
            Url.cshtml <-- to be used by any view in any area
        /EditorTemplates
            EmailAddress.cshtml <-- to be used by any view in any area
            Time.cshtml <-- to be used by any view in any area
            Url.cshtml <-- to be used by any view in any area
        _Layout.cshtml <-- master layout page with sections
        Error.cshtml <-- custom page to show if unhandled exception occurs
    _ViewStart.cshtml <-- won't be used automatically in an area
    Web.config <-- put custom HTML Helper namespaces in here

这意味着,如果您正在使用WidgetController之类的东西,则必须在其他文件夹中查找相关的WidgetViewModels,WidgetViews,WidgetEditorTemplates,WidgetDisplayTemplates等。尽管这很麻烦,但我坚持并没有偏离这些MVC约定。至于将模型,控制器和视图放在同一文件夹中但具有不同的命名空间,我避免了这一点,因为我使用了ReSharper。它会在与该类所在的文件夹不匹配的名称空间下模糊地加下划线。我知道我可以关闭此R#功能,但对项目的其他部分有帮助。

对于非类文件,MVC提供了开箱即用的内容和脚本。再次,我们尝试将所有静态/未编译文件保留在这些位置,以遵循惯例。每当我们合并使用主题(图像和css)的js库时,主题文件都放在/ content下的某个位置。对于脚本,我们只需将它们全部直接放入/ scripts。最初,这是为了从VS获取JS intellisense,但现在无论从/ scripts中放置什么,我们都可以从R#获取JS intellisense,我想我们可以偏离这一点,按文件夹划分脚本以更好地组织。您在使用ReSharper吗?它是纯金IMO。

T4MVC是另一个对重构有很大帮助的黄金。使用此方法,我们无需为区域名称,控制器名称,操作名称甚至内容和脚本中的文件键入字符串路径。T4MVC强烈为您键入所有魔术字符串。这是一个小样本,说明您使用T4MVC时项目结构的重要性如何:

// no more magic strings in route definitions
context.MapRoutes(null,
    new[] { string.Empty, "features", "features/{version}" },
    new
    {
        area = MVC.PreviewArea.Name,
        controller = MVC.PreviewArea.Features.Name,
        action = MVC.PreviewArea.Features.ActionNames.ForPreview,
        version = "december-2011-preview-1",
    },
    new { httpMethod = new HttpMethodConstraint("GET") }
);

@* T4MVC renders .min.js script versions when project is targeted for release *@
<link href="@Url.Content(Links.content.Site_css)?r=201112B" rel="stylesheet" />
<script src="@Url.Content(Links.scripts.jquery_1_7_1_js)" type="text/javascript">
</script>

@* render a route URL as if you were calling an action method directly *@
<a href="@Url.Action(MVC.MyAreaName.MyControllerName.MyActionName
    (Model.SomeId))">@Html.DisplayFor(m => m.SomeText)</a>

// call action redirects as if you were executing an action method
return RedirectToAction(MVC.Area.MyController.DoSomething(obj1.Prop, null));

2.数据访问:我没有使用过PetaPoco的经验,但是我确信值得一试。对于复杂的报表,您是否考虑过SQL Server报表服务?或者,您是否在其他数据库上运行?抱歉,我不清楚您到底要什么。我们使用EF + LINQ,但我们也对如何在域类中生成报告投入了一定的知识。因此,我们拥有控制器调用域服务调用存储库,而不是直接拥有控制器调用存储库。对于临时报告,我们使用SQL Reporting Services,这仍然不是完美的选择,但是我们的用户希望能够轻松地将数据引入Excel,而SSRS使得这一切变得容易。

3.客户端代码组织和UI渲染:我想可以在这里提供一些帮助。从《 MVC入门》和《 AJAX入门》一书中摘录。考虑一下:

<img id="loading_spinner" src="/path/to/img" style="display:none;" />
<h2 id="loading_results" style="display:none;">
    Please wait, this may take a while...
</h2>
<div id="results">
</div>
<input id="doSomethingDangerous" class="u-std-ajax" 
    type="button" value="I'm feeling lucky" 
    data-myapp-confirm="Are you sure you want to do this?"
    data-myapp-show="loading_spinner,loading_results" 
    data-myapp-href="blah/DoDangerousThing" />

现在忽略ajax成功功能(稍后再介绍)。您可以通过一个脚本来执行一些操作:

$('.u-std-ajax').click(function () {
    // maybe confirm something first
    var clicked = this;
    var confirmMessage = $(clicked).data('myapp-confirm');
    if (confirmMessage && !confirm(confirmMessage )) { return; } 

    // show a spinner?  something global would be preferred so 
    // I dont have to repeat this on every page 
    // maybe the page should notify the user of what's going on 
    // in addition to the dialog?
    var show = $(clicked).data('myapp-show');
    if (show) {
        var i, showIds = show.split(',');
        for (i = 0; i < showIds.length; i++) {
            $('#' + showIds[i]).show();
        }
    }

    var url = $(clicked).data('myapp-href');
    if (url) {
        $.ajax({
            url: url,
            complete: function () {                     
                // Need to hide the spinner, again would prefer to 
                // have this done elsewhere
                if (show) {
                    for (i = 0; i < showIds.length; i++) {
                        $('#' + showIds[i]).hide();
                    }
                }
            }
        });
    }
});

上面的代码将负责确认,显示微调器,显示等待消息,并在ajax调用完成后隐藏微调器/等待消息。您可以使用data- *属性(例如非侵入式库)配置行为。

一般的问题

-客户端MVC与服务器MVC?我没有尝试解放成功函数中执行的操作,因为它看起来像您的控制器正在返回JSON。如果您的控制器返回JSON,则可能需要查看KnockoutJS。Knockout JS 2.0版今天发布。它可以直接插入您的JSON,以便可以观察到的点击可以将数据自动绑定到您的javascript模板。另一方面,如果您不介意ajax操作方法返回HTML而不是JSON,则它们可以返回已构造的UL及其LI子级,并且可以使用data-myapp-response =将其附加到元素上“结果”。您的成功函数将如下所示:

success: function(html) {
    var responseId = $(clicked).data('myapp-response');
    if (responseId) {
        $('#' + responseId).empty().html(html);
    }
}

总结一下,我的最佳答案是,如果必须从操作方法返回JSON,则跳过了服务器端View,因此这实际上不是服务器MVC,而只是MC。如果将带有html的PartialViewResult返回给ajax调用,则这是服务器MVC。因此,如果您的应用必须为ajax调用返回JSON数据,请使用客户端MVVM(如KnockoutJS)。

无论哪种方式,我都不喜欢您发布的JS,因为它会将布局(html标记)与行为(异步数据加载)混合在一起。选择具有部分html视图的服务器MVC或具有纯JSON viewmodel数据的客户端MVVM将为您解决此问题,但是在javascript中手动构造DOM / HTML会违反关注点分离。

-Javascript文件创建显然,.NET 4.5中提供了缩小功能。如果您走的很顺畅,那么应该没有什么阻止您将所有JS加载到1个脚本文件中。我会为每种实体类型创建不同的JS文件时要小心,最终会导致JS文件爆炸。请记住,一旦加载了脚本文件,浏览器应将其缓存以备将来使用。

-复杂的查询我认为分页,排序等功能并不复杂。我的首选是使用URL和服务器端逻辑来处理此问题,以根据需要限制数据库查询。但是,由于我们已部署到Azure,因此查询优化对我们很重要。例如:/widgets/show-{pageSize}-per-page/page-{pageNumber}/sort-by-{sortColumn}-{sortDirection}/{keyword}。EF和LINQ to Entities可以使用.Take()、. Skip()、. OrderBy()和.OrderByDescending()等方法处理分页和排序,因此您可以在db旅行期间获得所需的内容。我还没有找到需要clientlib的需求,所以说实话我对它们了解不多。寻找其他答案以获取更多建议。

-Project Silk从来没有听说过这个,将不得不检查一下。我是Steve Sanderson,他的书,BeginCollectionItem HtmlHelper和他的博客的忠实拥护者。就是说,我没有在生产中使用KnockoutJS的经验。我已经检查了它的教程,但是在它的版本至少为2.0之前,我尽量不做任何事情。就像我提到的,KnockoutJS 2.0刚刚发布。

-N层如果按层表示不同的物理机器,那么不,我认为任何窗口都不会出错。通常,三层意味着您有3台计算机。因此,您可能有一个胖客户端作为您的表示层,可以在用户的​​计算机上运行。胖客户端可能会访问服务层,该服务层运行在应用程序服务器上,并向胖客户端返回XML或其他内容。服务层可能会从第三台计算机上的SQL Server获取其数据。

MVC是一层,位于1层上。控制器,模型和视图都属于表示层的一部分,表示层是物理体系结构中的1层。MVC实现了“模型-视图-控制器”模式,在这里您可能会看到其他层。但是,请尽量不要将这三个方面视为层或层。尝试将所有这三个问题视为表示层问题。

在pres / bus / data注释后更新

好的,因此您可以互换使用层和层。我通常将术语“层”用于逻辑/项目/程序集划分,将层用于物理网络分离。对困惑感到抱歉。

您会在MVC阵营中找到很多人,他们说您不应将MVC中的“模型”用于实体数据模型,也不应将控制器用于业务逻辑。理想情况下,您的模型应该是特定于视图的ViewModel。使用诸如Automapper之类的东西,您可以将您的实体从域模型中提取出来,并将它们DTO放入ViewModels中,该实体专门为视图而雕刻。

任何业务规则也应该属于您的域,您可以使用域服务/工厂模式/在域层(而不是MVC表示层)中适当的方式来实现它们。控制器应该是愚蠢的,尽管不像模型那样愚蠢,并且应该对域负责任何需要业务知识的事情。控制器管理HTTP请求和响应的流程,但是任何具有实际业务价值的事物都应高于控制器的薪资等级。

因此,您仍然可以使用MVC作为表示层的分层体系结构。它是应用程序层,服务层或域层的客户端,具体取决于您如何设计它。但是最终,您的实体模型应该是域的一部分,而不是MVC中的模型。


我完全同意这个答案!特别是:•Resharper是MVC的天才……从错误检查到IDE导航,其实用性令我震惊!• 服务器端MVC几乎总是最好的方法•MVC不是3个单独的层,它是一个表示层-我从没真正考虑过这种方法,但这是绝对正确的。
Scott Rippey

很好的答案,绝对是我要花300代表的费用。如果您在多伦多地区

顺便说一句,我一直认为N层是Pres / Bus / Data,无论他们坐在哪里。这就是为什么我说MVC几乎删除了该体系结构,因为它基本上结合了3,您说的有些同意,但是也给出了不同的看法。

我会警告不要使用ViewModel(按视图模型)方法。最近,我遇到一种情况,后来我希望我没有从DTO到ViewModel的抽象。请参阅:stackoverflow.com/q/7181980/109456

通常,我不喜欢看到jQuery,而是编写具有接口的对象,这些接口使任何服务器端开发人员都可以通过JQ或DOM API在内部进行业务快速理解。我也非常喜欢Django的URLConfig概念,并发现它对于设置要在页面上实现的对象很有帮助。我不知道是什么MV?图书馆应该为我做。它们不是完美解决问题的方法,IMO和DOM +事件委托是我处理页面时所需要的所有模型,而又不必过度依赖于特定的结构。
Erik Reppen 2013年

6

我不会写一个完整的答案,但想分享一些技巧。

我的提示:

1.项目结构
我发现默认的MVC结构对我不利。我通常同时使用同一实体(例如产品,订单,客户)的控制器,视图和模型。因此,我喜欢将文件放在同一文件夹中,但使用不同的命名空间。

2.数据
如果使用Linq-to-SQL或EF,您稍后会后悔。
我使用PetaPoco,它使我可以运行SQL检索和更新记录,而不会造成映射麻烦,但是却无需学习新的处理方式,也不会遇到性能方面的噩梦。

我有一个代码生成器,用于使用PetaPoco属性创建初始POCO类,然后在添加或删除某些字段时更改该类。

PetaPoco可处理动态和标准类,因此您不会有任何妥协(Massive是动态的,而Dapper是所有标准类的)

我还使用内置的SqlBuilder 生成了一个 SQL,该 SQL包含该实体的所有标准联接,但是没有WHERE的联接,因此我重复使用同一SQL来检索一个实体或列表。

3. jQuery 您可以使用通用的jQuery调用(将一些数据填充到HTML元素中)使UI的某些部分标准化。

例如,我有这个要删除。

var deleteLinkObj;
// delete Link
$('.jbtn-borrar').click(function () {
    deleteLinkObj = $(this);  //for future use
    $('#delete-dialog').dialog('open');
    return false; // prevents the default behaviour
});
$('#delete-dialog').dialog({
    autoOpen: false, width: 400, resizable: false, modal: true, //Dialog options
    buttons: {
        "Borrar": function () {
            $.post(deleteLinkObj[0].href, function (data) {  //Post to action
                if (data == 'OK') {
                    deleteLinkObj.closest("tr").hide('fast'); //Hide Row
                }
                else {
                    alert(data);
                }
            });
            $(this).dialog("close");
        },
        "Cancelar": function () {
            $(this).dialog("close");
        }
    }
});

我只需要将类添加jbtn-borrar到超链接,它会显示一个对话框,删除记录并隐藏tr

但是不要想太多。您的应用程序将在每个视图中轻触一下即可发光。

客户端MVC与服务器MVC
服务器MVC。利用可以在初始渲染中使用的局部视图,并使用同一视图使用Ajax刷新某些部分。看到这篇优秀的文章

如何处理复杂的查询(称为“报告”)
我使用具有Report参数作为属性的类(方便使用MVC自动映射)和Generate执行查询并填充自定义类列表的方法(如果您不这样做)没有适合ViewModel的类)
您可以使用此类作为视图的模型,并用生成的列表填充表。

微软的Project Silk被
过度架构。在相反的方向上尽可能快地运行。


有趣的是,当我阅读Project Silk时,我一直感到这种this的感觉,无法放置。

3

1.项目结构

我的解决方案中有2个项目文件

1)服务/业务层我将所有业务逻辑,数据库访问代码和POCO放入此单独的项目中。如果您使用ORM,则不需要数据访问层,因为ORM已经抽象了数据库层。

2)UI层包含我所有的视图,控制器,模型,脚本,CSS

我试图使我的控制器,视图,脚本和CSS都使用类似的文件夹结构。还要使我的文件结构尽可能与URL路径匹配。避免必须编写自定义路由。

尽可能使用DisplayTemplates,EditorTemplates,Partial视图和Shared文件夹。

然后,我将所有脚本构造为与c#文件的相同区域,控制器匹配,因此,我在根目录下将有一个common.js文件,每个页面都有一个js文件,每个区域都有一个common.js文件。

CSS文件我通常有2 + n(其中n是区域数)1st CSS文件是CSS,仅用于着陆页,只是为了帮助缩短页面加载时间(对于企业/公司环境可能不那么重要)2st CSS文件是common.css,具有所有其他页面的所有样式。然后是每个区域的另一个common.css文件,例如AdminArea.css文件,每个管理页面都有CSS。

2.数据访问

如果我使用实体框架,那么我将使用CodeFirst,因为它与POCOS配合得很好,并且您没有维护模型。nHibernate功能更强大,但具有逐步学习的曲线。对于分页数据库结果,我有一个可重用的util c#类和用于所有视图的patial视图。

对于复杂的查询和生成报告,我使用存储过程。它们更容易编写和维护,并为LINQ提供更多功能。它们也可以被其他服务(如SSRS)重用。我使用自动映射器将返回的数据集转换回使用的POCO entry框架。

3.客户端代码组织和UI渲染

Eduardo Molteni的答案有一个很好的示例代码。另外,我绝对建议您使用淘汰模板,因为它具有良好的模板和绑定能力。如果您对所有的AJAX调用都使用JSON(我经常使用JSON),那么将UI自动映射到JS对象将节省大量时间。

一般的问题

复杂的查询应存在于存储的proc中。(请参阅emeraldcode.com评论)

您仍然可以使用此MVC保持N层体系结构。


1

最近,我感动到,如果您打算使用列出的三种技术,那么首先应该假设采用Orchard CMS。我相信这是对您的中心需求的最佳单一答案:

在组织代码和逻辑,同时保持可伸缩性和创建丰富,快速,干净的UI的能力时,最佳策略是什么?

在Ochard场景中,您无法通过其配置机制解决的任何问题,您都可以通过添加免费的在线模块或编写自己的模块(当然是C#,razor等)来处理。代码组织是果园的力量。

至于数据访问,对于全口径ORM有很多利弊,我也认为微ORM是最好的选择。尝试MassiveDapper。两者都出现在Hanselminutes上。我将通过这样总结两个:SQL的抽象几乎总是随着项目的扩展而分解。最后,用于数据库访问的最佳解决方案是这种称为SQL的抽象(有点讽刺,但确实如此)。让微型ORM与此配合工作,您就拥有了金子。

将果园和微型ORM放在一起,就可以像黄油一样切成薄片。嗯,这意味着您可以快速发展,扩展规模,并拥有易于接手的团队维护的代码。


0

不知道我怎么错过了这个问题,但是两年后我会再加上两分钱。

客户端MVC与服务器MVC?我的项目已经是服务器端MVC结构,因此仍然需要Backbone.js提供的客户端MVC吗?

MVC和MV?甚至在将其推向客户端之前,它基本上已经演变成一个营销术语,它实际上仅承诺以某种方式将数据与其他东西分开,这在很大程度上是一个不错的主意,但DIY并不是那么困难。无论您采用哪种方法,在对HTML进行更改以影响表示或交互可能性的更改之前或之中,这都是整理企业希望您如何处理数据的绝对最糟糕的地方。

“视图逻辑”没有什么特别的。相同的原理应适用于所有逻辑。也就是说,现在不要做任何比现在更有意义的事情。在传递数据或启动新流程之前,如果所有鸭子都排成一排,那么前一阶段很可能对系统中执行类似操作的其他任何对象具有更高的可重用性。

是否应该为每个对象(例如OrderHeader.js)创建Javascript文件,然后在构建过程中将其缩小/合并?还是应该只包含一个具有OrderHeader,OrderDetails,Reports等逻辑的Order.js?

这实际上取决于您,但我会尽量摆脱一文件一类的问题。我从未理解过为什么为什么有帮助,例如必须找到抽象文件和接口以及实现的文件等。对更广泛的关注进行分类。ctrl + f有点长,使用起来并不难。

就是说,您永远不要重组JS来缩小Web文件的大小。浏览器缓存JS,因此您可以通过将旧JS粘贴在新文件中来强制重新加载相同的JavaScript。除非有数量惊人的JavaScript,否则您一次不应该在页面上拥有所有JS的情况是,在给定的条件下,永远不需要大量的特定于站点某一部分且没有重叠/灰色区域的JS页。

而且,FFS不会对Web上的JavaScript进行依赖关系管理大惊小怪。中低复杂性网站上的Require.js让我想成为小海豹。将您的第三方库放在最重要的位置。您的内部图书馆在第二块。然后在第三部分中,您的实现代码(永远不应是内部库代码的十分之一,即非常简洁,清晰易懂)。

如何处理复杂的查询?现在,我的主要理论是/ Reports / Orders-By-Date /或类似的东西,我使用了一个自定义SQL查询,该查询将自定义数据集(或ViewModel)呈现到Razor View。但是分页,排序等呢?这样做是在客户端还是在服务器端更好?(假设较大的数据集-2至3秒的SQL查询)我已经阅读了Microsoft的Project Silk。这是个好方法吗?与Backbone.js或其他产品相比如何?

老实说,我想说的是,对您来说更轻松的事情,不会对客户造成影响。网页非常快地加载了现代技术。如果用Ajax实施对您来说很痛苦,那就不要。只需使用您最了解的内容,然后您就可以看上一眼,看看自己喜欢如何进行分页。如果您要从头开始构建新的复杂应用程序,请从基本开始,然后再打个整洁。

我非常习惯于N层体系结构,这些概念是否将其排除在外?看起来MVC就像是过去的前端或顶层中的一堆微型N层部分。

这真的取决于谁对什么MV有幻想的想法?是。海事组织,微观世界往往运作良好。在内部将数据,通信和与视图相关的内容分开的一类小部件非常有用。在客户端网络上,最重要的事情是IMO,要保持关注点分离的平衡,而又不必分散成微小的关注点,因为这些关注点的重新组合使理解,重用和修改内容变得困难。基本的“ duh” OOP在这里很好用。您不需要复杂的流程。您想要明显命名的事物,可以四处移动并指示其执行操作。这方面的一些技巧:

  • 亲吻(OOP)接口,我不希望看到DOM或jQuery或其他任何棘手的服务器端开发人员都无法在我的实现代码中很快找到答案。该人只需要知道在div容器上拍上什么类以及在给定页面上进行活动以使相当通用的一组UI翻转即可。主题的变体仍应通过传递有据可查/有注释的选项对象来完成,然后才开始查看document.get <anything>或了解CSS的最基本基础之外的任何内容。

  • 好的,那你怎么做?好,我们已经有一个模型。它称为DOM。我们有事件委托。如果您不是不加选择地关闭事件冒泡(不要这样做,因为它很有用,它就在那儿了),您可以根据需要甚至从身体中捡起每个东西。然后检查传递的事件对象的目标属性,并确定谁是“无所不包”的人。如果您明智地构建HTML文档,则没有理由不将其用作委托模型。行为和内容结构是自然联系在一起的。两者具有重叠的标识符是可以的。

  • 不要为数据绑定买单,“支付”我当然是指“在您的代码库上放一个库,坚持让您一直在做事情,以便获得奇迹般的收益,而这实际上并不难做”。JQ的事件系统非常简单。

时间示例:

function PoliticianData(){ //a constructor

    var
        that = this, //I hate 'that' but example so convention

        flavorsOfLie = {

            lies: "Oh Prism? Psh... no we're all good. There's a guy keeping an eye on that.",

            damnedLies: "50% of the people chose to not give a damn when asked whether it was better to let the terrorists win or not give a damn."

        }
    ;//end instance vars

    this.updateLies = function( lieType, newData ){
        flavorsOfLie[lieType] = newData;
        $(that).trigger({type:'update', lieType:lieType, newData: newData });
    }

    //so everytime you use the updateLies method, we can have a listener respond
    //and pass the data
}

var filthyLies = new PoliticianData();

$(filthyLies).on('update', function(e){
    stickNewDataInHTMLWithSomeFuncDefinedElsewhere(e.lieType, e.newData);
} );

filthyLies.update('damnedLies','50% of the people said they didn\'t give a damn');
//oh look, WaPo's front page just changed!
  • 不要隐藏网络在所有早期尝试中,使服务器端和应用程序开发人员易于使用客户端的主要努力源于这一关键点。HTTP请求并非如此,而且从未如此复杂。他们并不需要18!@#$ ing层来使每个阶段的事件名称混乱,以使其更易于理解。同样,有很多关于客户端的知识,但是没有理由通过在其顶部拍一个巨大的模型来隐藏与之交互的HTML和DOM。它已经是一个巨大的巨型模型,并且效果很好。我们需要做的是使其更易于管理,这是一些明智的OOP实践以及一些JS和DOM知识。

  • 支持灵活性

EXTjs <====灵活性比例====> jQuery(不一定是其任何插件)

IMO,可让您快速进行DIY的工具始终是更好的选择。只有在您的头顶上没有人特别挑剔细节并且您不介意将控制权移交给本来可以帮助您的事情时,为您完成所有工作的工具才是正确的选择。我实际上已经看过验证HTML的插件,以确保您不会在其中具有所有相同的确切显示特征的情况下偷偷摸摸。为什么?我只有理论。我认为这可以归结为让完成人员真正讨厌某人以一种不想要的方式使用自己的东西的想法,而这总是不可避免地有人希望您在UI中执行的操作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.