我发现Angular对模型的使用令人困惑。 Angular似乎采用了一种模型可以随心所欲的方法-即Angular不包括显式的模型类,您可以将原始JavaScript对象用作模型。

在我所见过的几乎每个Angular示例中,模型实际上都是手动创建的对象,或者是通过Resource通过API调用返回的对象。因为我看过的几乎每个Angular示例都很简单,所以通常将模型数据存储在$ scope中的 Controller 中,并且与模型相关的任何状态(例如选择)也都存储在 Controller 中的$ scope中。这对于简单的应用程序/示例来说效果很好,但是当应用程序变得更加复杂时,这似乎过于简化了。例如,如果上下文发生更改,则存储在 Controller 中的模型状态可能会变得上下文相关并丢失。存储selectedGalleryselectedPhoto的Controller只能存储全局selectedImage,而不是每个图库的selectedPhoto。在这种情况下,每个画廊使用一个 Controller 可能会解决此问题,但从UI angular 看似乎很浪费,而且可能是不合适和不必要的。

Angular对模型的定义似乎更接近我认为的VO/DTO,它是在服务器和客户端之间传递的一个愚蠢的对象。我的直觉是将这样的对象包装在我认为的模型中-一种类,该类维护与DTO/VO相关的状态(例如选择),根据需要提供变体来操纵DTO/VO,并通知其余对象对基础数据进行更改的应用。显然,Angular的绑定(bind)很好地照顾了最后一部分,但是我仍然看到前两个职责的强大用例。

但是,我在所查看的示例中并未真正看到过这种模式,但是我也没有看到我认为可伸缩的替代方案。 Angular似乎通过强制使用Singletons隐式地不鼓励使用Services作为模型(我知道有解决此问题的方法,但是它们似乎并未得到广泛使用或认可)。

那么我应该如何保持模型数据的状态呢?

[编辑] this question中的第二个答案很有趣,接近我当前正在使用的答案。

最佳答案

状态(和模型)存储在$ scope中

$ scope是Angular的数据存储对象。它类似于数据库。 $ scope本身不是模型,但是您可以将模型存储在$ scope中。

每个$ scope都有一个父$ scope,一直到$ rootScope形成一个松散地镜像您的DOM的树结构。当您调用需要新$ scope的指令(例如ng-controller)时,将创建一个新的$ scope对象并将其添加到树中。

$ scope对象使用原型(prototype)继承进行连接。这意味着,如果在树中的较高级别添加模型,则所有较低级别的模型都可用。这是一个非常强大的功能,它使$ scope层次结构几乎对模板作者透明。

Controller 初始化$ scope

Controller 的目的是初始化$ scope 。同一 Controller 可以在页面的不同部分初始化许多$ scope对象。实例化 Controller ,设置$ scope对象,然后退出。您可以使用同一 Controller 在页面的不同部分初始化许多$ scope。

对于图片库,您将有一个imageGallery Controller ,然后使用ng-controller指令将其应用于要成为图库的DOM的每个部分。页面的该部分将获得其自己的$ scope,您可以使用它来存储selectedPhoto属性。

原型(prototype)范围

$ scope一直使用普通的原型(prototype)原型(prototype)继承其父级,直到$ rootScope,因此您可以将对象存储在层次结构中有意义的任何位置。您将获得一棵$ scope对象树,该树与您当前的DOM大致相关。如果您的DOM更改,则会根据需要为您创建新的$ scope对象。

$ scope只是一个普通的JavaScript对象。创建多个$ scope对象比创建具有多个currentImage对象的数组没有浪费。这是组织代码的明智方式。

这样,Angular消除了JavaScript中经常出现的旧的“我在哪里存储数据”问题。这是我们从Angular获得的最大的生产力提升之一。

有全局数据(例如,一个userId)?将其存储在$ rootScope上。有本地数据(例如,在存在多个画廊实例的画廊中的currentImage)?将其存储在属于该库的$ scope对象上。

您可以在模板的正确部分自动使用$ scope。

angular 模型很薄

来自我们强调胖模型和瘦 Controller 的Rails背景,我发现Angular的“几乎没有”模型令人惊讶。实际上,在模型中放置很多业务逻辑经常会导致一系列问题,正如我们有时会在Rails中的User模型中看到的那样,如果您不小心的话,它会一直增长到无法维护为止。

angular 模型只是JavaScript对象或图元。

任何对象都可以是模型。模型通常是使用 Controller 中的JSON定义的,或者是通过服务器AJAX输入的。模型可能是JSON对象,也可能只是字符串,数组甚至是数字。

当然,没有什么可以阻止您向模型中添加其他函数并将它们存储在JSON对象中的,但是,这将移植到与Angular并不完全匹配的范例中。

angular 对象通常是数据的存储库,而不是函数。

前端的模型不是真实模型

当然,您在客户端上持有的模型不是真实模型。您的实际模型和唯一的事实来源都存在于服务器上。我们使用API​​进行同步,但是如果两者之间存在冲突,那么数据库中的模型显然是最终的胜利者。

这为您提供了诸如折扣代码等之类的隐私权。您在前端找到的模型是真实模型的公共(public)属性的同步版本,该模型是远程的。

业务逻辑可以存在于服务中。

假设您要编写一种方法来对模型执行某些操作,对其进行同步或进行验证(例如)。在其他框架中,您可能会想使用一种方法来扩展模型。在Angular中,您更有可能编写服务。

服务是单例对象。像其他任何JavaScript对象一样,您可以在其中放置函数或数据。 Angular附带了一堆内置服务,例如$ http。您可以构建自己的应用程序,并使用依赖注入(inject)将它们自动提供给 Controller 。

服务可能包含与RESTful API进行通信或验证数据或可能需要执行的其他任何工作的方法。

服务不是模型

当然,您不应该将服务用作模型。将它们用作可以做事的对象。有时他们会对您的模型起作用。这是一种不同的思维方式,但可行的。

关于javascript - 模型状态应存储在Angular.js中的何处,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16607874/

10-12 13:05