在knockout.js中编写使用点击的组合条件

Writing combined conditions to work with click in knockout.js

本文关键字:组合 条件 js knockout      更新时间:2023-09-26

我不知道如何正确编写允许在knockout.js中调用click的条件。我设法创建了4个按钮,当我点击它们时,一个可观察的数组将填充它们的值。我想防止在这个数组中传递相同的值,还想防止传递超过2个值。我的起始代码是:

<table>
    <tr>
        <td>
            <input type="button" value="1" data-bind="click: hasBeenAdded() || isFull() ? null : function() { addNumber(1); }">
        </td>
        <td>
            <input type="button" value="2" data-bind="click: hasBeenAdded() || isFull() ? null :function() { addNumber(2); }">
        </td>
        <td>
            <input type="button" value="3" data-bind="click: hasBeenAdded() || isFull() ? null : function() { addNumber(3); }">
        </td>
        <td>
            <input type="button" value="4" data-bind="click: hasBeenAdded() || isFull() ? null : function() { addNumber(4); }">
        </td>
    </tr>
</table>
<h3>Available columns created by the user</h3>
Column: <strong data-bind="text: column"></strong>

我的观点模型是:

function viewModel() {
        var self = this;
        self.hasBeenAdded = ko.observable(false); 
        self.isFull = ko.observable(false);
        self.column = ko.observableArray();
        self.addNumber = function(data) {
            //console.log('Added ', data);
            self.hasBeenAdded = true;
            self.column.push(data);
        }
        if (self.column().length > 3) {
            self.isFull = ko.observable(true);
        }
    }

你能帮我正确地编写hasBeeAdded和isFull布尔值来处理点击数据绑定吗?

我认为您想要一个按钮的值数组,而不是显式地创建每个值。这样,就可以使用foreachclick绑定将获得该值作为其数据参数。

hasBeenAdded应该是一个开始为空的字典,您可以检查单击的项是否在addNumber中。

要正确打印列,您需要foreach或使用join将数组转换为字符串。

function viewModel() {
  var self = this;
  self.hasBeenAdded = ko.observable({});
  self.numbers = [1, 2, 3, 4];
  self.isFull = ko.observable(false);
  self.column = ko.observableArray();
  self.addNumber = function(data) {
    if (!self.hasBeenAdded[data]) {
      self.hasBeenAdded[data] = true;
      self.column.push(data);
    }
  };
  if (self.column().length > 3) {
    self.isFull = ko.observable(true);
  }
}
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table>
  <tr data-bind="foreach:numbers">
    <td>
      <input type="button" data-bind="value: $data, click: $parent.addNumber">
    </td>
  </tr>
</table>
<h3>Available columns created by the user</h3>
Column: <strong data-bind="text: column().join(',')"></strong>

Knockout是一个MVVM风格的库。养成在视图模型中编写所有逻辑的习惯,让视图只反映这些视图模型的状态。首先,看看computed可观察性是如何工作的。

在实践中,这意味着您放置在视图中的所有逻辑都应该在单击处理程序中。此外,你似乎想要:

  • 如果用不合适的值调用点击处理程序,则不会发生任何事情
  • 该按钮在某些情况下被禁用

下面是一个如何做到这一点的例子:

function ViewModel() {
  var self = this;
  
  self.column = ko.observableArray([]);
  self.hasBeenAdded = function(data) {
    return self.column.indexOf(data) >= 0;
  }
  
  self.isFull = ko.computed(function() {
    return self.column().length > 1;
  });
  
  self.canAdd = function(data) {
    return !self.isFull() && !self.hasBeenAdded(data);
  }
  self.addNumber = function(data) {
    if (self.canAdd(data)) {
      self.column.push(data);
    }
  }
}
ko.applyBindings(new ViewModel());
input[type="button"] { background-color: white; }
input[type="button"]:disabled { background-color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<table>
    <tr>
        <td>
            <input type="button" value="1" data-bind="click: function() { addNumber(1); }, enable: canAdd(1)">
        </td>
        <td>
            <input type="button" value="2" data-bind="click: function() { addNumber(2); }, enable: canAdd(2)">
        </td>
        <td>
            <input type="button" value="3" data-bind="click: function() { addNumber(3); }, enable: canAdd(3)">
        </td>
        <td>
            <input type="button" value="4" data-bind="click: function() { addNumber(4); }, enable: canAdd(4)">
        </td>
    </tr>
</table>
Column: <strong data-bind="text: column"></strong>

不过,您也有一些其他问题,最值得注意的是您的代码不是很枯燥。但考虑到你在问题中发布的代码与我之前建议的DRY有关,我认为你有理由不改变它?