【问题标题】:Knockout ViewModel separation, whats the general approach/best practice?淘汰 ViewModel 分离,一般方法/最佳实践是什么?
【发布时间】:2013-05-27 04:59:28
【问题描述】:

我刚开始搞砸 Knockout JS,我有以下场景(示例)。

我有一个游客列表,该列表包含 CRUD 方法 - 一切都很好。现在,当我单击一个游客时,将显示更详细的描述 - 这是对该信息的服务器的新 AJAX 调用。

我的问题是,我是否应该有 1 个包含我的 TouristsViewModel 和 TouristsInfoViewModel 的主视图模型 - 这意味着应该将 TouristsViewModel 与主视图耦合以修改 TouristsInfoViewModel,或者我应该TouristsViewModel 实例化TouristsInfoViewModel 并调用ko.applyBindings?

我查看了Knockout-postbox,但我想避免引入太多的 3rd 方插件。

总结一下:分离视图和视图模型同时能够在它们之间共享数据的一般方法是什么?

【问题讨论】:

    标签: mvvm knockout.js viewmodel dry separation-of-concerns


    【解决方案1】:

    这是一个通用的方法。

    1. 花时间学习 AMD,而 require.js 就是一个很好的库。
    2. 保持视图模型分开,不要耦合它们。
    3. knockout-postbox、amplify.js pub/sub 非常适合相互交流。
    4. 查看单页应用程序框架。 Durandal 是一个不错的选择。
    5. 如果您不打算使用 Durandal 或 SPA,即使这样,也可以创建一个单独的模块来处理您的敲除绑定。
    6. 每个视图都应该有一个对应的视图模型。
    7. 将您的 ajax 调用分离到它自己的模块中。例如: TouristRepository.js 可能是一个模块,它将为您进行所有 ajax 调用。
    8. 使用承诺。 Q.js 或 jquery 的延迟承诺会帮助你。你的仓库应该返回 Promise。
    9. 您的视图模型应该只是……本质上,它应该保持状态并提供视图交互处理程序。模型应该是它自己的文件。然后 ViewModel 可以保存模型数据。
    10. 只能通过存储库检索模型数据。

    我认为这将是一种不错的方法,并且对您有用。

    编辑 - 根据评论添加更多内容。

    1) 您可以在 requirejs 中使用 shimming 和 export 来加载 ko 验证插件,而不是使用 define。除非你一开始没有使用 requirejs 来加载它。

    2) 使用 pub/sub 不是耦合。当一个模块完全依赖于另一个模块的功能或存在时,就会发生耦合。考虑到 MasterViewModel 直接与另一个 viewmodel 通信是耦合的。在发布/订阅场景中,您的一个视图模型(称为 Persons.js)是说保存一个人对象。保存后,应该会更新本地缓存。在这种情况下,Persons.js 在保存后会发送一条消息说“Person saved”并传递它拥有的任何数据。 ClearCache.js 负责清除缓存。它只是在侦听“人员已保存”消息以采取一些行动。耦合方式是 Persons.js 实例化 ClearCache 并直接调用它的 clearCache 方法。因此,要存在 Persons.js,clearCache.js 必须存在。而在 pub/sub 中,即使 clearCache.js 不存在,Persons.js 也可以继续存在。

    3) 这个问题的答案完全取决于您的应用要求。通常,我有一个名为 binder.js 的中间模块。 binder.js,监听消息。因此,假设用户想要查看详细信息并点击游客。 TouristsViewModel 将发布一条消息“Tourist Detail Requested”并传递一个游客 ID 或一些信息。绑定器正在监听这个,知道要实例化哪个视图模型以及要采取什么行动。这样一来,您的 ToursistsViewModel 就完全不知道 TouristsInfoViewModel。如果在另一个视图中,您列出了所有游客的名字和姓氏并且不必显示详细信息,则可以重复使用 TouristsViewModel,而无需引入 TouristsInforViewModel。在这种情况下不需要 MasterViewModel。

    您的应用程序听起来像是单页应用程序的完美候选者。遵循“一个视图 - 一个 ViewModel”方法和“单一职责”方法。 TouristsViewModel 只显示游客,TouristInfoViewModel 将显示游客信息。两个人都对彼此毫无头绪。我最近在一个有类似要求的项目上工作。演讲者,演讲者详细信息,会议,会议详细信息。我的视图模型都不知道另一个。它们都通过客户端路由和哈希更改事件进行管理。

    【讨论】:

    • 谢谢,这是有道理的!我已经在使用 Require,它很棒,除了我必须将 KO Validation 插件包装在 define() 中以使其正常工作。分离 AJAX 调用,好主意!我可能会将其命名为 TouristApi.js 或 TouristService.js,但无论如何!使用邮箱/放大,这不被认为是“耦合”吗?另外,根据我的问题,我将如何管理视图模型?从主视图模型?主视图模型是否应该一次实例化所有视图模型?请详细说明!暂时+1。 :)
    • 在我的回答中添加了更多内容。希望对您有所帮助。
    • 关于 KO Validation 的匀场,我试过但没有用,但似乎是一个已知的错误 (github.com/Knockout-Contrib/Knockout-Validation/issues/104),所以我只是继续将它包装在一个定义调用中,它是都好。关于binder,在我的场景中那会是我的 MasterViewModel 吗?另外,为什么你推荐使用 Promise?
    • binder 会不会是它自己的模块。您可以拥有一个 main.js(引导程序)来加载它并在您的应用程序启动时保持其正常运行(它不会是主视图模型)。关于 Promise,这是处理我们所说的“回调地狱”的更好方法。考虑到这一点,您只有 1 个成功处理程序。您可能会根据您的第一个结果进行更多的 ajax 调用,依此类推。你最终会得到一堆嵌套的回调。有了承诺,你可以做这样的事情 Q.When(_firstAjaxCall).then(function(_firstAjaxResult){})
    • 我开始使用 Durandal,效果非常好!感谢您的建议!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-21
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 2014-09-29
    • 2013-03-15
    • 2011-06-07
    相关资源
    最近更新 更多