【问题标题】:Knockout/MVVM Design Concern淘汰赛/MVVM 设计问题
【发布时间】:2012-06-13 07:39:13
【问题描述】:
我正在努力解决在使用 KnockoutJS 框架和 MVVM 时不断出现的问题。有时,集合中特定项目的属性发生更改,并且由于该更改,我需要影响同一集合中的所有其他项目。在所有语言和模式中,一个对象不应该“知道”它所在的集合的任何信息,但我发现自己需要经常打破这条规则才能让某些类型的逻辑正常工作。
我创建了一个人为的示例来说明我正在谈论的内容,以展示我解决这个问题的方法。我希望有更多经验的人可以参与并告诉我更好的方法。
JSFiddle Contrived Example
【问题讨论】:
标签:
javascript
design-patterns
mvvm
knockout.js
【解决方案1】:
我不知道这是否是“推荐”的方法,但我会就如何解决这个问题提出我的建议。我不是 MVVM 专家(尽管我已经编写了很多 KnockoutJS 应用程序),但我认为一些 OOP 原则对这里的帮助已经绰绰有余了。
所以首先让我们讨论一下目前的情况......
您的方法,正如您正确观察到的那样(敲除双关语无意!),并不理想 - Person 对象不仅知道他们的兄弟姐妹(即使通过订阅间接地知道),而且知道他们所在的父对象订阅 - 您的 Person 类型订阅了父级的更改。这不仅使您的 Person 对象在此场景之外无法使用,而且还赋予每个实例过多的责任(违反单一责任原则),并且每个实例都订阅了其他实例的更改,这当然是浪费!
那么解决办法是什么?
对我来说,放置这种逻辑的理想位置是在您的父对象(即您的视图模型)上。您的视图模型已经知道它的子对象,那么为什么不把功能放在那里呢?这将使您的 Person 类型可在其他地方重用(好的,因此它具有可观察对象,因此目前它与 KO 相关联,但这可以通过 Mapping 插件克服)并减轻其管理其兄弟姐妹的责任。
但这仍然意味着父母和孩子之间存在紧密耦合——这不是我们在 OOP 中想要的!为了克服这个问题,您可以采用 pub/sub(观察者)模式并让您的 Person 类型在发生变化时发布消息,然后您可以让订阅者(例如您查看模型)决定如何响应此事件。您也不一定需要使用淘汰赛的 pub/sub 产品,任何 pub/sub 实现都可以。虽然您也可以利用 KO 提供的功能,但我会为您指出这些扩展/帮助程序的方向,以使事情变得更简单:http://www.knockmeout.net/2012/05/using-ko-native-pubsub.html
希望对我有所帮助:)
【解决方案2】:
除非我误解了您的情况,否则您可以使用自动动态更新的 computed observables。
首先,我认为每个人的“未成年”财产标志只是将他们的年龄与分钟进行比较。年龄。例如19.
其次,您还可以使用computed observable 为所有用户做一个聚合标志。
最后,我不一定同意这是父子关系。这些只是特定于页面的视图模型的属性。
查看这个在这两种情况下都使用计算的示例。
http://codepen.io/anon/pen/ufKCo