AngularJS 客户端 MVC 模式?

AngularJS client MVC pattern?

提问人:PrimosK 提问时间:10/25/2012 最后编辑:Koray TugayPrimosK 更新时间:7/19/2021 访问量:41093

问:

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

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


来自 AngularJS 教程

对于 Angular 应用,我们鼓励使用 Model-View-Controller (MVC) 设计模式,用于解耦代码并分离关注点。

来自维基百科模型-视图-控制器

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


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

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

这是否意味着 MODEL 和 CONTROLLER 在某种程度上是重复的(客户端/服务器)?

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

JavaScript 模型-视图-控制器 客户端 AngularJS 服务器端

评论


答:

117赞 Roy Truelove 10/25/2012 #1

这根本不是一个奇怪的问题 - 我一直在尝试将 Angular 出售给许多 java 开发人员,他们问了这个问题。我在学习时自己问过(顺便说一句,我还在学习)

如果你采用你所描述的“传统”java webapp,并对其进行Angular-ize,你必须首先获取你的服务器,并使其成为一个RESTful API。删除 JSP 等。这实际上是编写 Angular 应用程序的困难部分,IMO——正确获取 REST API。对我来说,决定进入服务器需要什么逻辑的关键是将其视为一个纯粹的 api,暂时忘记了它将有一个前端

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

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

那么 Angular 端的 MVC 是什么呢?

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

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

  1. 一个 REST API,需要健壮且可用,无需前端
  2. 一个 GUI,需要向用户提供即时反馈,而不必等待服务器。

所以,简短的回答 - 通过忘记会有 UI 来获得正确的 REST API,并且 Angular 中的内容会更清晰。

评论

1赞 Roy Truelove 1/9/2013
仅供参考,自从写这篇文章以来,我决定不使用 REST,而是使用尽可能类似于 Amazon 的 EC2 API 的 HTTP API。REST并不能解决问题。对不起,餐馆老板!
2赞 stefcud 5/14/2013
下一代框架解决了客户端和服务器中的逻辑重复问题,请参阅 meteor.com
1赞 Kr0e 12/19/2013
不一定,流星解决了重复问题,但也提高了限制。拥有 RESTful API 和 WebUI 非常有用(使用相同的 REST API 编写本机应用程序)。IMO 流星是一个很好的概念,但它与服务器端的耦合太紧密,无法在任何情况下都有用。当然,使用流星;)可以更容易地解决很多问题
0赞 Thiago C. S Ventura 7/29/2014
这确实是一个很好的答案,但根据我的经验,Java 需要在 restful api 应用程序方面有所改进,在尝试了 ExpressJS 之后,我放弃了 Spring MVC。
1赞 php-dev 10/29/2014
@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.
13赞 Ben Lesh 10/25/2012 #2

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

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

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

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

至于你的“业务”逻辑或规则......任何需要安全性的东西都必须始终在服务器级别受到保护。

评论

0赞 imanis_tn 5/23/2014
几年来,AngularJS 更接近 MVC(或者更确切地说是它的客户端变体之一),但随着时间的推移,由于许多重构和 API 改进,它现在更接近 MVVM——$scope对象可以被认为是 ViewModel,它正在被我们称为 Controller 的函数修饰。
5赞 Always Learning 7/11/2014
上面的评论引用了 AngularJS 团队的一篇文章:plus.google.com/app/basic/stream/......
3赞 Aladdin Mhemed 10/28/2012 #3

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

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

我鼓励逐渐接受它,慢慢地慢慢走,但可以肯定的是,我保证,当然。

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

评论

1赞 Roy Truelove 11/10/2012
绝对正确。我鼓励我办公室里的其他开发团队使用 Angular,即使他们的应用程序中有最微小的 javascript。
3赞 Enrique Molinari 11/10/2012 #4

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

  • 信用卡应有效。
  • 如果您使用 X 品牌的信用卡付款,您将获得 10% 的折扣。
  • 购物车应至少包含一件商品以执行结账
  • 在允许用户将其添加到购物车之前,物料必须有库存

这些需求的实现将对你的问题域进行建模,这是你的业务逻辑。

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

您可以查看一个示例应用程序,它遵循此处提到的原则。

3赞 CalebC 6/21/2013 #5

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

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

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

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

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

8赞 Niko Bellic 8/19/2014 #6

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

AngularJS "MVC"

2赞 Yogi 11/19/2015 #7

我的方法始终是自下而上的方法。从数据库设计开始,使用正确构造/相关的表,在需要时使用存储过程,然后将实体框架添加到解决方案中,或者如果 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 请求的端点。