AngularJS的单个对象模型

neh*_*iah 5 javascript model-view-controller model angularjs angularjs-scope

我正在AngularJS中尝试一些特别是设计模型的最佳实践.我认为AngularJS的一个真正的力量是

'当模型更改视图得到更新时,反之亦然'

.这导致了明显的事实

"在任何特定时间,模型都是应用程序状态的唯一真实来源"

现在,在阅读了关于设计正确模型结构的各种博客文章后,我决定使用类似"单一对象"的方法.这意味着整个应用程序状态都保存在一个JavaScript对象中.

例如待办事项

$scope.appState = {
name: "toDoApp",
auth: {
    userName: "John Doe",
    email: "john@doe.com",
    token: "DFRED%$%ErDEFedfereRWE2324deE$%^$%#423",
},

toDoLists: [        
  { name: "Personal List", 
    items: [
      { id: 1, task: "Do something ", dueDate: "2013-01-10 11:56:05", status:"Open", priority : 0},
      { id: 2, task: "Do something ", dueDate: "2013-01-10 11:56:05", status:"Open", priority : 1},
      { id: 3, task: "Do something ", dueDate: "2013-01-10 11:56:05", status:"Open", priority : 0}]
  }, 
  { name: "Work List", 
    items: [
      { id: 1, task: "Do something ", dueDate: "2013-01-10 11:56:05", status:"Open", priority : -1},
      { id: 2, task: "Do something ", dueDate: "2013-01-10 11:56:05", status:"Open", priority : 0},
      { id: 3, task: "Do something ", dueDate: "2013-01-10 11:56:05", status:"Open", priority : 0}]
  }, 
  { name: "Family List", 
    items: [
      { id: 1, task: "Do something ", dueDate: "2013-01-10 11:56:05", status:"Open", priority : 2},
      { id: 2, task: "Do something ", dueDate: "2013-01-10 11:56:05", status:"Open", priority : 0},
      { id: 3, task: "Do something ", dueDate: "2013-01-10 11:56:05", status:"Open", priority : 5}]
  }
]        
Run Code Online (Sandbox Code Playgroud)

};

根据应用程序的复杂性,此对象将变为巨大.关于这一点,我有以下的担忧,并将其标记为问题.

  • 这种方法是否可取?当应用程序开始扩展时,我将面临哪些缺点和缺陷?

  • 如果对象的一小部分被更新,则表示优先级增加,角度会单独智能地重新渲染增量,还是会考虑对象被更改并重新渲染整个屏幕?(这将导致表现不佳),如果是这样的话,有什么作用?

  • 现在,由于整个DOM被平滑地转换为一个JavaScript对象,因此应用程序必须继续操作此对象.我们是否有适合复杂JavaScript对象操作的工具,比如jQuery是DOM操纵器的王者?

有了上述疑虑,我强烈地发现了以下优点.

  • 数据已经整齐抽象和组织良好,以便随时可以将其序列化为服务器,firebase或本地导出到用户.

  • 实现崩溃恢复很容易,将此功能视为桌面中的"Hibernate"选项.

  • 模型和视图完全分离.例如,公司A可以编写模型来维护状态,很少有明显的控制器来更改模型和一些基本视图来与用户交互.现在,该公司A可以邀请其他开发人员公开编写自己的视图,并请求公司A获取更多控制器和REST方法.这将有助于精益开发.

  • 如果我开始将此对象版本化到服务器并且我可以以相同的方式向用户播放他看到网站并且可以继续工作而不会有麻烦.这将作为单页应用程序的真正后退按钮.

Luc*_*eis 3

在我的日常工作中,我们在大型企业 AngularJS 应用程序中使用“单个对象中的状态”模式。到目前为止我只能看到好处。让我来解答您的问题:

这种方法可取吗?当应用程序开始扩展时,我将面临哪些缺点和陷阱?

我看到两个主要好处:

1)调试。当应用程序扩展时,最难回答的问题是我的应用程序现在发生了什么?当我将所有应用程序状态保存在一个对象中时,我可以在应用程序运行时随时将其打印在控制台上。

这意味着发生错误时更容易理解发生了什么,您甚至可以在生产中使用应用程序来执行此操作,而无需使用调试工具。

使用处理状态对象(或其部分)的大部分纯函数编写代码,在控制台中注入这些函数和状态,然后您将拥有最好的调试工具。:)

2)简单。当您使用单个对象时,您可以非常清楚地知道应用程序中什么更改了状态以及什么读取了状态。它们是完全独立的代码片段。让我用一个例子来说明:

假设您有一个“结帐”屏幕,其中包含结帐摘要、运费选项和付款选项。如果我们实现SummaryFreight并且PaymentOptions具有单独的内部状态,则意味着每次用户更改其中一个组件时,您都必须显式更改其他组件

因此,如果用户更改选项Freight,您必须Summary以某种方式调用,告诉它更新其值。如果用户选择PaymentOption有折扣的产品,也会发生同样的情况。你能看到意大利面条式的代码构建吗?

当您使用集中式状态对象时,事情会变得更容易,因为每个组件仅与状态对象交互Summary只是国家的纯粹功能。当用户选择新的运费或付款选项时,状态会更新。然后,Summary会自动更新,因为状态刚刚改变。

当更新一小部分对象时,比如优先级增加,角度会智能地单独重新渲染增量,还是会考虑对象已更改并重新渲染整个屏幕?(这会导致性能不佳),如果是的话,有什么解决方法?

在将这种架构与 Angular 一起使用时,我们遇到了一些性能问题。当您在对象上使用观察者时,角度脏检查效果很好,但当您使用昂贵的函数时,效果就不太好。因此,当发现性能瓶颈时,我们通常所做的是将函数结果保存在设置为 的“缓存”对象中$scope。每次状态改变时,我们都会再次计算函数并将其保存到缓存中。然后在视图上引用这个缓存。

现在,由于整个 DOM 顺利地转换为一个 JavaScript 对象,应用程序必须继续操作该对象。我们是否有合适的工具来进行复杂的 JavaScript 对象操作,就像 jQuery 是 DOM 操作器之王一样?

是的!:) 因为我们有一个大对象作为我们的状态,所以每个为操作对象而编写的库都可以在这里使用。

您提到的所有好处都是真实的:它使拍摄应用程序快照、序列化它、实现撤消变得更容易......

我在我的博客中写了一些集中式状态架构的更多实现细节

还要查找有关基于中心化国家思想的框架的信息,例如OmMercuryMorearty

  • 这是一个经过深思熟虑的书面答案,通过充分理解这个问题,它也与我的观点产生了很大的共鸣。当我最初问这个问题时,我感到很奇怪,因为我无法从互联网人群中找到这样的模式。不管怎样,祝你好运,几个月前我就停止使用 Angular,为了快速目的,我使用了一种叫做 CanJS 的东西,所以轻松如微风。 (2认同)