AngularJS 客户端 MVC 模式?

Posted

技术标签:

【中文标题】AngularJS 客户端 MVC 模式?【英文标题】:AngularJS client MVC pattern? 【发布时间】:2012-10-15 13:53:24 【问题描述】:

到目前为止,我主要使用Struts 2SpringJQuery 技术栈来构建 Web 应用程序。关键是,提到的堆栈使用服务器端MVC 模式。 Web 浏览器的主要作用仅限于请求/响应周期(+ 客户端验证)。数据检索、业务逻辑、布线和验证是服务器端的主要职责。

我对 AngularJS 框架有几个问题,这些问题的灵感来自我读过的以下引言:


来自AngularJS tutorial

对于 Angular 应用,我们鼓励使用模型-视图-控制器 (MVC) 设计模式来解耦代码和分离关注点。

来自Wikipedia Model–view–controller

模型-视图-控制器 (MVC) 是一种将 来自用户交互的信息表示 它。该模型由应用程序数据和业务规则组成, 控制器调解输入,将其转换为命令 模型或视图


AngularJS 使用客户端 MVC 模式。所以我想没有其他选择以某种方式将验证逻辑也包含到客户端?

编写健壮的 AngularJS 应用程序的最佳方式是什么?客户端的 MVC 和服务器端的某种 MC(模型、控制器)?

这是否意味着 MODEL 和 CONTROLLER 以一种方式重复(客户端/服务器)?

我知道我的问题有点奇怪,但我认为原因是,我在某种程度上习惯了传统的服务器端 MVC 模式。我确信有人已经完成了相同的转换。

【问题讨论】:

【参考方案1】:

我的方法始终是自下而上的方法。从数据库设计开始,在需要时使用正确构造/相关的表和存储过程,然后将实体框架添加到解决方案中,如果不能选择 EF,则使用 ADO.Net。然后开发业务逻辑和模型以将数据输入和输出数据库。

建立模型后,我们现在可以走两条路线:开发 MVC 控制器,和/或开发 WebAPI 控制器。两个控制器都可以访问模型,这只是实例化类和调用方法的问题。

您现在可以选择设置由 MVC 控制器控制的 MVC 视图,或者完全独立的 html 页面集或 SPA(NodeJS 上托管的单页应用程序)。

使用完全独立的 HTML 页面集,您将需要使用 WebAPI 控制器,以及 Get、Post、Put 和 Delete 方法,并确保来回包含令牌以识别您的客户端,并启用 CORS(对于跨域请求)

使用 MVC 视图,您可以使用控制器属性和/或会话来识别您的客户端,而无需担心 CORS,如果需要,您甚至可以将视图设置为强类型。不幸的是,如果您有一组 UI 开发人员,他们将不得不使用相同的 MVC 解决方案。

在这两种情况下,您都可以使用 AngularJS 在控制器之间来回传输数据。

恕我直言,AngularJS 控制器的概念与 C# MVC 或 C# WebAPI 控制器不同。 AngularJS 控制器包含所有 javascript 逻辑以及通过“ApiFactory”对端点的调用,而 C# 控制器只不过是服务器端接受和响应 UI 请求的端点。

【讨论】:

【参考方案2】:

这根本不是一个奇怪的问题——我一直在尝试将 Angular 推销给很多 Java 开发人员,他们会问这个问题。我在学习的时候问过自己(我还在学习,顺便说一句)

如果您采用您所描述的“传统”java webapp 并对其进行 Angular 化,您必须首先采用您的服务器并将其设为 RESTful API。删除 JSP 等。这实际上是 IMO 编写 Angular 应用程序的难点——正确获取 REST API。对我来说,决定哪些逻辑需要进入服务器的关键是将其视为纯粹的 api,而暂时忘记它会有前端

这个问题对我很有帮助 - 如果有人尝试保存给定资源并且该资源没有有效数据,则没有前端可以告诉他们 - 他们直接访问 API,因此 API 需要拒绝它。因此,后端负责深度验证。这也适用于您的业务逻辑。假设有人使用只是 API,那么您的服务器需要做什么就会变得很清楚。

服务器还需要(可能)以 json 格式发送数据(我使用 Spring MVC + Jackson),因此它负责将模型暴露给 Angular,并与数据库进行通信。

那么 Angular 端的 MVC 是什么?

模型:来自 REST API 的数据。如果 API 正在出售 JSON,那么这些对象将已经是 1 类 javascript 对象。 查看:HTML,以及需要操作 DOM 时的指令 控制器:(以及您从控制器中提取的自定义服务......) 查询 REST API 并将视图所需的内容放在 $scope 上 为指令提供回调,以响应可能需要回调服务器的事件。 验证:通常通过对指令的回调。 可能会与您已经在服务器中进行的一些验证重叠,但您不希望您的用户等待服务器验证所有内容 - 客户端应该知道一些事情 em> 关于验证,以便为用户提供即时反馈。 业务逻辑:与验证几乎相同。

但是为什么在客户端和服务器中出现重复的逻辑呢?主要是因为您不是在编写一个应用程序,而是在编写两个独立的东西:

    一个 REST API,需要在没有前端的情况下保持健壮和可用 需要立即向用户提供反馈而不一定要等待服务器的 GUI。

所以,简短的回答 - 通过忘记会有 UI 来正确使用 REST API,而 Angular 中的内容会更加清晰。

【讨论】:

仅供参考,自从写这篇文章以来,我决定不使用 REST,而是使用尽可能类似于 Amazon 的 EC2 api 的 HTTP api。 REST 只是没有削减它。对不起,restafarians! 下一代框架解决了客户端和服务器中的重复逻辑,参见meteor.com 不一定,meteor 可以解决重复问题,但也会增加限制。拥有 RESTful API 和 WebUI 非常有用(使用相同的 REST API 编写本机应用程序)。 IMO meteor 是一个很好的概念,但它与服务器端的耦合过于紧密,无法在任何情况下都派上用场。当然,使用流星可以更轻松地解决很多问题;) 这确实是一个很好的答案,但是根据我的经验,Java 需要在 restful api 应用程序方面有所改进,在尝试了 ExpressJS 之后我放弃了 Spring MVC。 @RoyTruelove 哇!伟大的! +1顺便说一句。好吧,IMO,最有说服力的部分是:But why the duplication of logic in the client and in the server? Mostly because you're not writing one app, you're writing two independent things: 1) a REST API that needs to be robust and usable without a front end 2) a GUI that needs to give immediate feedback to a user and not necessarily wait for a server. So, short answer - get the REST API right by forgetting that there will be a UI, and what goes into Angular will be much clearer. 谢谢!【参考方案3】:

重要的是要了解,在 MVC 模式的某些版本中,数据以及操作数据的逻辑都驻留在“模型”层( “控制器”层除了绑定什么都不做)。然而,在 AngularJS 中,数据($scope)单独驻留在“模型”层中,而操作数据的逻辑($scope)驻留在“控制器”层中。

【讨论】:

【参考方案4】:

我似乎也有这个问题,因为一些组织只是热衷于新技术 - “我想要云......等等,我想要轻量级”,很难证明它是否值得切换到更轻量级的框架.

我一直使用 Spring/JBoss seam/JSF 和 MVC 框架开发 Web 应用程序。大多数情况下,Java 脚本将驻留在表示层验证中,而主要的操作类/实体和业务逻辑将驻留在 Java 代码中。在对 Angular 进行了一些基本的实践之后,我开始理解 MVC 的含义,因为他们在表示层上抽象了另一个层次,我们可以在前端拥有自己的视图和控制器。要回答您的问题,就像每个人的评论一样,最好的方法是将其放在表示层上。

从安全的角度来看,我认为繁重或敏感的业务规则应该驻留在服务器端,因为我们不想将其暴露给世界。如果业务逻辑开发不好,很容易找到我们代码的弱点并加以利用。

这是我对像 Angular 这样的框架的想法,就像一个小商店/SOHO 处理客户,他们有几个人,而且非常高效和快速。它们很好地满足了面临业务和高效交付/接收货物的客户(REST,JSON) .他们确实有指定的角色和任务,但有些工人执行的不仅仅是任务。这家商店也容易受到小偷或强盗的攻击,因为他们通常不强调严密的安全性。

对于像 Spring/Struts 2 这样的服务器端框架,想象一个具有不同管理级别并能够处理更大业务(批处理作业、Web 服务、企业总线)的现代公司(CMM 5 级)。他们确实与客户打交道,但不是直接的,经常通过经纪人甚至零售店。安全方面,公司更强大,通常前门有证券,或重要信息被保护在保险箱中(加密/登录)。

【讨论】:

【参考方案5】:

我同意这里的答案。还有一些cmets。当您编写应用程序时,您首先需要专注于问题域。并创建一些真实业务的软件模型。例如,如果您的问题域是购物,您需要建模的一些需求可能包括:

信用卡应该是有效的。 如果您使用品牌 X 的信用卡付款,您将获得 10% 的折扣。 购物车应至少包含一件商品以执行结帐 商品必须有库存才能让用户将它们添加到购物车

这些需求的实现将为您的问题域建模,这是您的业务逻辑。

Angular 是一个前端框架和工具包。它是一个 web 前端。如果您在 Web 前端实现此功能,您将错过从其他前端或界面(如移动或桌面应用程序)重用模型的机会。 因此,理想情况下,您的业务逻辑实现需要与任何用户界面框架分离,也需要与任何持久性框架分离。然后,您将拥有将处理用户界面问题并与您的业务逻辑对象通信的界面对象。这可以是 Spring MVC 控制器,和/或 Angular 控制器或服务。

有一个sample application你可以看看,遵循这里提到的原则。

【讨论】:

【参考方案6】:

我喜欢@Roy TrueLove 所说的话。但是让我说这是使用 angularjs 的终极方式。当然,如果你想获得 Angular 的最大好处,你必须学会​​用这种方式来做你的应用程序。我祈祷有一天能在那里。

与此同时,在你学习的过程中,以及在你过渡到完全使用 angularjs 作为你的客户端主要做事方式的过程中,你可以开始到处使用它来完成一些小任务,并逐渐习惯它并它的思维方式。

我鼓励逐渐拥抱它,慢慢地慢慢走,但我保证,当然。

Angularjs 旨在服务于这种方法,因为它可以处理最小的任务,也可以处理最大的任务。例如,我第一次使用 angular 只是为了在用户键入 id 时显示名称。

【讨论】:

绝对正确。我鼓励我办公室的其他开发团队使用 Angular,即使他们的应用程序中只有最少量的 javascript。【参考方案7】:

我认为“业务逻辑”一词在这里有点用词不当。客户端应用程序的“业务”是处理用户界面的业务。它不会是诸如安全规则和专有逻辑或其他敏感知识产权之类的东西。

所以在 Angular 中,划分是(通常):

Controller(控制器):用于操作 UI 背后的数据(范围)。 指令:用于设置 DOM 以通过范围与控制器通信,用于操作 DOM。 模板(视图):将指令分配给 DOM 的元素。 Scope(模型或视图模型):用于在系统的所有部分之间传输数据。 服务:可注入、可重用的代码。通常用于处理 Ajax、cookie 或其他 I/O 等依赖项。

实际上几乎是 MVVM 而不是 MVC。

至于您的“业务”逻辑或规则……任何需要安全的东西都必须始终在服务器级别进行保护。

【讨论】:

多年来 AngularJS 更接近于 MVC(或者更确切地说是它的客户端变体之一),但随着时间的推移,由于许多重构和 api 改进,它现在更接近于 MVVM - $scope 对象可以被认为是被我们称为控制器的函数修饰的 ViewModel。 以上评论引自 AngularJS 团队的一篇帖子:plus.google.com/app/basic/stream/…

以上是关于AngularJS 客户端 MVC 模式?的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS入门

使用 AngularJS 配置 Spring MVC

使用AngularJS配置Spring MVC

是否可以在 MVC 局部视图中运行 AngularJS 应用程序

正确格式化 AngularJS 的 ASP.NET MVC 日期

AngularJS笔记