草庐IT

javascript - AngularJS 的单对象模型

coder 2025-03-16 原文

我正在 AngularJS 中试验一些最佳实践,特别是在设计模型方面。在我看来 AngularJS 的一个真正的力量是

'When model changes view gets updated & vice versa'

.这导致了显而易见的事实

'At any given time the model is the single source of truth for application state'

现在,在阅读了有关设计正确模型结构的各种博客文章后,我决定使用类似“单一对象”的方法。这意味着整个应用程序状态都在单个 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}]
  }
]        

};

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

  • Is such approach advisable? What are the downsides and pitfalls I will face when application starts to scale?

  • When small portion of object is updated say priority is increased will angular smartly re-render the delta alone or will it consider the object got changed and re-render whole screen? (This will lead to poor performance), If so what are the works around?

  • Now since the whole DOM got smoothly translated into one JavaScript object the application has to keep manipulating this object. Do we have right tools for complex JavaScript object manipulation like jQuery was king of DOM manipulator?

带着以上疑惑,我强烈地发现了以下优点。

  • 数据已被整齐地抽象和组织得井井有条,以便随时 可以序列化到服务器、firebase 或本地导出到用户。

  • 实现崩溃恢复将很容易,将此功能视为桌面中的“休眠”选项。

  • 模型和 View 完全分离。例如,公司 A 可以编写 Model 来维护状态,并编写几个明显的 Controller 来更改 模型和一些与用户交互的基本 View 。现在这家公司A 可以邀请其他开发者公开写下自己的看法, 向公司 A 请求更多的 Controller 和 REST 方法。这个 将赋能精益开发。

  • 如果我开始将此对象版本控制到服务器,我可以以用户查看网站的相同方式向用户播放,并且可以继续轻松工作,会怎样?这将作为单页应用程序的真正后退按钮。

最佳答案

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

Is such approach advisable? What are the downsides and pitfalls I will face when application starts to scale?

我看到两个主要好处:

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

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

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

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

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

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

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

When small portion of object is updated say priority is increased will angular smartly re-render the delta alone or will it consider the object got changed and re-render whole screen? (This will lead to poor performance), If so what are the works around?

我们在将此架构与 Angular 一起使用时遇到了一些性能问题。当你在对象上使用观察者时,Angular 脏检查工作得很好,但当你使用昂贵的函数时效果不佳。因此,我们在发现性能瓶颈时通常做的是将函数结果保存在 $scope 上设置的“缓存”对象中。每次状态改变时,我们都会重新计算函数并将其保存到缓存中。然后在 View 上引用此缓存。

Now since the whole DOM got smoothly translated into one JavaScript object the application has to keep manipulating this object. Do we have right tools for complex JavaScript object manipulation like jQuery was king of DOM manipulator?

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

您提到的所有好处都是真实的:它可以更轻松地拍摄应用程序的快照、序列化它、实现撤消...

我又写了一些implementation details of the centralized state architecture in my blog .

同时查找有关基于集中状态思想的框架的信息,例如 Om , MercuryMorearty .

关于javascript - AngularJS 的单对象模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24054950/

有关javascript - AngularJS 的单对象模型的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  4. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  5. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  6. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  7. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  8. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  9. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  10. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

    我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

随机推荐