我对ockoutout.js有点陌生,但是我无法确定将某些操作放在可观察数组上的位置。这是我的代码:

var Building = function() {
    var self = this;
    self.nLocation = ko.observable();
    self.nBuilding = ko.observable();
    ...
    self.increaseLocNum = function() {
        self.nLocation(self.nLocation + 1);
    };
}
var Quote = function() {
    var self = this;
    var nQuoteID = ko.observable();
    ...
    self.buildings = ko.observableArray([]);
    self.addBuilding = function(){
        ...
        // Build new building with next loc/building number
        buildings.push();
    }
    ...
}
ko.applyBindings(new Quote());


因此,基本上我的报价中可以包含多个建筑物。每个建筑物都绑定到选项卡控件上的不同选项卡。在这些标签上是一个“位置”字段,带有+/-按钮,用于增加/减少位置编号。

我需要使用“启用”绑定来设置+/-按钮的启用(例如,如果某建筑物是唯一具有最高位置编号的建筑物。以下是一些简单规则的示例:


如果建筑物位于位置1,则不能减少位置号
如果建筑物是位置最高的唯一建筑物,则不能增加位置编号
如果只有一栋建筑物,则位置编号无法增加


逻辑很简单,但是我迷失了遵循最佳淘汰赛实践的逻辑。

最佳答案

减少功能很容易,因为单个建筑物的视图模型不需要知道任何外部因素即可做出决定;它可以根据其可观察的位置直接计算。增加功能比较棘手,因为它取决于集合中所有其他建筑物的状态。

这是一种避免子类不必了解父类的选项。在每个建筑物上放置canIncrease观测值,但让父视图模型处理实际的增/减,以便它可以遍历所有子级并在更改位置时更新其观测值。



var Building = function(location) {
  var self = this;
  self.nLocation = ko.observable(location);
  self.nBuilding = ko.observable("-Building Name Here-");

  self.canIncrease = ko.observable(); //set by parent
  self.canDecrease = ko.computed(function(){
    //Location number can't be decreased if the building is at location 1
    return self.nLocation() > 1;
  });
}

var Quote = function() {
  var self = this;
  var nQuoteID = ko.observable();

  self.buildings = ko.observableArray([new Building(1)]);

  self.addBuilding = function() {
    // Build new building with next loc/building number
    self.buildings.push(new Building(self.highestLocation() + 1));
    self.enableChildren();
  }

  self.highestLocation = ko.computed(function(){
    var highest=0;
    $.each(self.buildings(), function(key,value){ if(value.nLocation() > highest) highest = value.nLocation(); });
    return highest;
  });

  self.increaseLocNum = function(building) {
    building.nLocation(building.nLocation() + 1);
    self.enableChildren();
  };
  self.decreaseLocNum = function(building) {
    building.nLocation(building.nLocation() - 1);
    self.enableChildren();
  };

  self.enableChildren = function(){
    //Location number can't be increased if the building is the only building on the highest location
    //Location number can't be increased if there is only one building
    $.each(self.buildings(), function(key, building){
        if(building.nLocation() === self.highestLocation() || self.buildings().length === 1){
          building.canIncrease(false);
        }else{
          building.canIncrease(true);
        }
    });
  }
}

ko.applyBindings(new Quote());

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<input type="button" data-bind="click: addBuilding" value="Add Building" />
<span style="margin-left: 8px;">Total Buildings: <label data-bind="text: buildings().length" /></span>
<span style="margin-left: 8px;">Highest Location: <label data-bind="text: highestLocation" /></span>
<br/>
<table>
  <thead>
    <tr>
      <th></th>
      <th>Location</th>
      <th>Building Name</th>
    </tr>
  </thead>
  <tbody data-bind="foreach: buildings">
    <tr style="border: 1px solid blue;">
      <td>
        <input type="button" data-bind="enable: canDecrease, click: $parent.decreaseLocNum" value="-" />
        <input type="button" data-bind="enable: canIncrease, click: $parent.increaseLocNum" value="+" />
      </td>
      <td>
        <span data-bind="text: nLocation"></span>
      </td>
      <td>
        <span data-bind="text: nBuilding"></span>
      </td>
    </tr>
  </tbody>
</table>

关于javascript - Knockout.js可观察的数组操作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42493997/

10-12 07:04