【问题标题】:How to seperate model from viewmodel in knockout?如何在淘汰赛中将模型与视图模型分开?
【发布时间】:2014-12-05 06:35:27
【问题描述】:

我有一个带有 observableArray 项目的模型,这很好。例如

var arr = ko.observableArray([{name: ko.observable('hello')}]);

我的问题是我想为这些不属于模型本身的项目设置一组单独的设置。在这种特殊情况下,我想跟踪选定的记录。

如果我把项目放在模型中,那是微不足道的。

ko.utils.arrayForEach(arr, function(item) { 
 item.selected = ko.observable(false); 
});

但这会永久性地改变模型,并破坏我想添加新元素的其他地方。

所以我尝试的是对数组进行可计算,但效果不佳。

var selected = ko.computed(function () {
 if (!arr()) return [];
 return ko.utils.arrayMap(arr().list(), function () {
  return ko.observable(false);
 });
});

因为它会记住返回的项目,所以当 arr 发生变化时,它会以奇怪的方式破坏事物。

如何将这两件事分开,同时仍保持同步?

【问题讨论】:

    标签: knockout.js model viewmodel durandal-2.0


    【解决方案1】:

    如果您使用复选框,最好的方法是将checkedValue 绑定为对象并将checked 绑定到根中的单独 observableArray。那么您使用复选框选择的每个项目都将位于根数组中。这与您所问的并不完全相同,但它是一个非常简单的解决方案,可以知道选择了哪个项目。

    如果您必须按照您指定的方式进行操作,您可能必须复制数组(或使用原始数组的所有键创建一个引用数组),然后使用foreach 绑定来列出对象并使用click 绑定将对象传递给函数,该函数将在引用数组中查找它并设置选定/未选定属性。

    还有其他选项,具体取决于您的 UI,因此可能提供更多相关信息会有所帮助。

    示例:

    <div class="form-group" data-bind="visible: sites().length">
     <label for="siteSelect" class="form-label col-sm-2"
      Sites
     </label>
     <div id="siteSelect" class="col-sm-10" data-bind="foreach:sites">
      <div  class="col-md-4 col-sm-6"">
       <input type="checkbox"
     data-bind="checkedValue: SiteId, checked: $root.selectedSites, text: Name">
       </input>
      </div>
     </div>
    </div>
    

    在我的 veiwmodel 中,我有:

    var vm = {
        sites: ko.observableArray([
            {SiteId: 1, Name: 'Site 1'},
            {SiteId: 2, Name: 'Site 2'},
            {SiteId: 2, Name: 'Site 3'}
        ]),
        selelctedSites: ko.observableArray([1]),
    }
    return vm;
    

    这告诉 knockout 为数组 'sites' 中的每个项目创建一个复选框,显示每个元素的 Name 属性,并使 SiteId 成为每个复选框的值(绑定:checkedValue)。 'selectedSites' 数组将为每个选定的项目提供一个元素,该元素将是 'checkedValue',或者在本例中为 SiteId。如上所示,默认情况下会选中“站点 1”的复选框。如果效果更好(给你一个选定对象的数组),你也可以让 checkValue 成为整个对象。我认为,这通常比尝试协调两个数组效果更好。

    如果这是您的首选界面,还有选择框选项(单选或多选)。

    希望这会有所帮助,如果您还有其他问题,请告诉我。

    【讨论】:

    • 没看懂你的意思,能举个例子吗?
    • @Cine,添加了一个示例。这有帮助吗?
    • 确实,这是一个很棒且非常简单的解决方案。我确实使用了checkedValue: $data,这让事情变得更加简单。
    【解决方案2】:
    //viewmodel
    define(function () {
      var ko = require('knockout'),
          items = ko.observableArray([]),
          selectedItems = ko.observableArray([]);
    
      return {
         items: items,
         selectedItems: selectedItems
      }
    
    });
    
    //view
    
    <!-- ko foreach: items -->
      <input type="checkbox" data-bind="checked: $parent.selectedItems, checkedValue: $data" />  
    <!-- /ko -->
    

    【讨论】:

      猜你喜欢
      • 2018-06-25
      • 1970-01-01
      • 1970-01-01
      • 2019-11-14
      • 2011-12-21
      • 1970-01-01
      • 2014-07-28
      • 2012-06-17
      • 2013-05-31
      相关资源
      最近更新 更多