我正在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}]
  }
]

};

根据应用程序的复杂性,该对象将变得很大。对此,我有以下担心,并将其标记为问题。



基于以上怀疑,我强烈地发现以下优点。
  • 数据已被整齐地抽象并组织得井井有条,以便随时随地
    可以序列化到服务器,firebase或本地导出到用户。
  • 实现崩溃恢复将很容易,请将此功能视为台式机中的“休眠”选项。
  • 模型和 View 完全分离。例如,公司A可以编写Model来维护状态,并且可以编写一些显而易见的Controller来更改状态。
    模型和一些与用户进行交互的基本 View 。现在这家公司A
    可以邀请其他开发者公开发表自己的观点,并
    要求公司A提供更多的 Controller 和REST方法。这
    将促进精益发展。
  • 如果我开始将此对象版本控制到服务器,并且可以以相同的方式向用户进行回放,他会看到该网站并且可以继续工作而不会遇到麻烦。对于单页应用程序,这将充当真正的后退按钮。
  • 最佳答案

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



    我看到两个主要好处:

    1)调试。 当应用程序扩展时,最难回答的问题是我的应用程序现在正在发生什么?当我将所有应用程序状态都放在一个对象中时,只要在应用程序运行时的任何时间点,都可以在控制台上将其打印出来。

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

    使用处理状态对象(或其一部分)的纯函数编写代码,并将这些函数和状态注入(inject)控制台,您将拥有可用的最佳调试工具。 :)

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

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

    因此,如果用户更改了Freight选项,则必须以某种方式调用Summary,以告知其更新其值。如果用户选择带有折扣的PaymentOption,则必须进行同样的操作。您能看到意大利面条的代码结构吗?

    当您使用集中式状态对象时,事情会变得更加容易,因为每个组件仅与状态对象进行交互。 Summary仅仅是状态的纯函数。当用户选择新的运费或付款方式时,状态将更新。然后,因为状态刚刚更改,所以Summary自动更新。



    在将此架构与angular一起使用时,我们遇到了一些性能问题。当您在对象上使用观察程序时, Angular 脏检查效果很好,而在使用昂贵的功能时效果不太好。因此,通常在发现性能瓶颈时要做的就是将函数结果保存在$scope上设置的“缓存”对象中。每次状态更改时,我们都会再次计算该函数并将其保存到缓存中。然后在 View 上引用此缓存。



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

    您提到的所有好处都是对的:它使对应用程序进行快照,序列化,执行撤消操作更加容易。

    我已经写了更多implementation details of the centralized state architecture in my blog

    还要查找有关基于集中式状态概念的框架的信息,例如OmMercuryMorearty

    09-25 19:11
    查看更多