【问题标题】:Passing KnockoutJS viewmodels in BoilerplateJS在 BoilerplateJS 中传递 KnockoutJS 视图模型
【发布时间】:2012-10-04 14:39:57
【问题描述】:

嵌套组件也预设了嵌套视图模型。

然而,在示例组件中,我没有看到这种依赖出现(除了 BackboneJS TODO 应用程序,对于 KO 用户来说不是很清楚)。

您能否详细说明如何进行这样的设计,例如对于一个集合:

  • ItemViewModel 具有属性 NameIsSelected
  • CollectionViewModel 有一个 Items 属性,其中包含 ItemViewModelSelectedCount 的集合,该集合是通过计算选择的项目数来计算的。 (我知道这可以通过 KO 以更简单的方式完成,但只是为了说明。

【问题讨论】:

  • 看看clickcounter的例子,它在父组件中有两个嵌套组件。这些嵌套组件不共享相同的视图模型,而是通过事件进行通信。另一方面,salesDashboard 组件中的两个子组件共享父组件的单一视图模型。我回答了吗?或者我是否错过了这个问题?
  • 我将我的问题编辑得更具体。事件或共享单个视图模型与嵌套视图模型不同 - 这更接近于您在 Silverlight 中执行 MVVM 的方式。
  • 仅供参考:查看 knockoutjs (knockoutjs.com/documentation/with-binding.html) 中的“with”绑定。在这里,您可以拥有一个父视图模型,在其中为每个组件嵌套子视图模型。然后在你的组件视图中,你可以使用'with'绑定来指定它需要绑定的子视图模型。
  • 嗯,是的……我想这就足够了。我会测试并报告。
  • 嗯...但是我如何将子视图模型传递给组件的initialize()?你能提供一个完整的例子吗?

标签: javascript boilerplatejs


【解决方案1】:

Viewmodels (VM) 只是对象(使用ko.applyBindings() 绑定) - 这意味着您可以将 VM 任意嵌套到父对象中(@Hasith 所说的)。您只需将 一个 父对象传回 Boilerplate。忍受一些超注释代码:

// Let's assume you have your items nicely formatted in an array 
// data source (and technically the objects in this array can be 
// considered 'dumb' viewmodels)
var items = [
  {Name:'a',isSelected:false}, 
  {Name:'b',isSelected:true}
  ]

// We can apply some bindings to make 'smarter' viewmodels
// One approach is just to map using rocking KO mapping plugin
var koMapItems = ko.mapping.fromJS( items )

// You could skip the mapping plugin and go for broke
// creating your own VM mappings manually
// (you could do this using the mapping plugin with less work)
var goforbrokeVM = function( item )
{
  var _name = ko.observable( item.Name )
  var _dance = function() { return _name+' is space monkey' }

  return {
    Name: _name,
    isSelected: ko.observable( item.isSelected ),
    spaceMonkey: _dance
  }
}
// Don't forget to assign and create your goforbrokeVMs
var epicItemVMs = []
for (var i=0;i<items.length;i++) 
  epicItemVMs.push( new goforbrokeVM( items[i]) )


// Now the interesting part, lets create a 'child' VM that
// we can embed in another VM. Notice this VM has as a
// property an array of VMs itself.
var childVM = {
  elements: epicItemVMs,
  // A sub method, because we can
  otherMethod: function() { return 'wat' }
}

// And ultimately our 'master' VM with its own properties
// including the nested child VM we setup above (which you'll
// remember contains its own sub VMs)
var ParentVM = {
  // And its own property
  parentPropA: ko.observable('whatever'),

  // Oooow look, a list of alternative ko.mapping VMs
  simpleMappedItems: koMapItems,

  // And a nested VM with its own nested goforbrokeVMs
  nested: childVM
}

// Apply your master viewmodel to the appropriate DOM el.
ko.applyBindings( ParentVM, document.getElementById('items'))

还有你的 HTML:

<div id="items">
  <span data-bind="text: parentPropA"></span>

  <!-- Step through one set of items in ParentVM -->
  <div data-bind="foreach: simpleMappedItems">
    <input type="checkbox" data-bind="checked: isSelected">
    <span data-bind="text: Name"></span>
  </div>

  <!-- Or jump into the nested models and go crazy -->
  <!-- ko with: nested -->
    <div data-bind="foreach:elements">
      <div data-bind="text: spaceMonkey"></div>
    </div>
    <div data-bind="text: otherMethod"></div>
  <!-- /ko -->
</div>

通过这种方式,您可以将单个对象(在本例中为 ParentVM)传递给带有尽可能多的嵌套视图模型的样板。

用于淘汰赛的地图插件信息在这里:http://knockoutjs.com/documentation/plugins-mapping.html

【讨论】:

    【解决方案2】:

    “todo”示例是通过采用 Addy Osmani 的实现来完成的。 还有一个knockoutjs的实现here

    【讨论】:

    • 对。但我对如何使用 KO 实现 TODO 不感兴趣,这很明显 - 只是如何使其与 BoilerplateJS 结构一起工作。
    猜你喜欢
    • 2014-04-03
    • 2012-10-02
    • 1970-01-01
    • 2021-12-01
    • 1970-01-01
    • 2013-07-26
    • 2015-07-19
    • 1970-01-01
    • 2015-10-31
    相关资源
    最近更新 更多