单击同一行中的按钮后递减值 - 挖空

Decrement a value after clicking a button in the same row - knockout

本文关键字:按钮 挖空 一行 单击      更新时间:2023-09-26

我有一个表格,我用一些数字填充。每行都有一个按钮。单击此按钮后,我想减少此行中的计数器。如何用淘汰赛来做到这一点?

<div class="panel panel-default">
    <div class=panel-heading>Title</div>
    <table class=table>
        <thead>
            <tr>
                <th>Counter</th>
                <th>Increment</th>                  
            </tr>
        </thead>
        <tbody data-bind="foreach: records">
        <tr>
            <td data-bind="text: counter"></td>             
            <td> <input type="button" value="increment" data-bind=??? ></td>
        </tr>
    </tbody>
    </table>
</div>
<script>
function AppViewModel() {
    var self = this;   
    self.records = ko.observableArray([]);   
    $.getJSON("/data", function(data) {         
      self.records(data);      
    }) 
//function to decrement
}
ko.applyBindings(new AppViewModel());
</script>

我会这样做:

  1. 处理从服务器获取的数据,将counter属性转换为可观察属性,并向递减计数器属性添加函数
  2. 稍微重组一下您的代码,以便在 ajax 请求时创建视图模型
  3. 将调用applyBindings移动到 ajax 回调,以便在加载所有内容后触发

因此,代码如下所示:

    <tr>
        <td data-bind="text: counter"></td>             
        <td> <input type="button" value="decrement" data-bind="click: decrement"></td>
    </tr>
    function AppViewModel() {
        var self = this;   
        self.records = ko.observableArray([]);
    }
    var vm = new AppViewModel();
    // load data from server
    $.getJSON("/data", function(data) {
        data.forEach( function(item) {
          // make counter observable
          item.counter = ko.observable(item.counter);
          // add function to decrement
          item.decrement = function() {
            this.counter( this.counter()-1 );
          }
        })
        // load array into viewmodel
        vm.records(data);
        // apply bindings when all obervables have been declared
        ko.applyBindings(vm);
    })

检查演示:小提琴

我更喜欢立即初始化并绑定我的视图模型,但同意其他海报的观点,即您需要一个可观察量。

这是一个解决方案,它继续立即创建和绑定您的视图模型,就像您的原始示例一样,但它不是您收到的原始记录数组,而是将它们转换为自己的小模型对象,这些对象具有计数器的可观察量和也可以绑定数据的增量函数。这会将数据加载与视图模型的生命周期分离,因此,如果您想添加一个按钮来加载新数据以覆盖它或类似的东西,这只是对getData()的又一次调用。

<!-- ... -->
    <tbody data-bind="foreach: records">
        <tr>
            <td data-bind="text: counter"></td>             
            <td> <input type="button" value="increment" data-bind="click: increment" ></td>
        </tr>
    </tbody>
<!-- ... -->
<script>
function AppViewModel() {
    var self = this;   
    self.records = ko.observableArray([]);   
    self.getData = function(){ /* ... */ };
    self.getFakeData = function(){
      var data = [{ counter: 1 }, { counter: 2}, { counter: 3 }];
      var freshData = data.map(function(record){
            return new AppRecord(record);
      });
      self.records(freshData);      
    };
}
function AppRecord(rawRecord) {
    var self = this;
    self.counter = ko.observable(rawRecord.counter);
    self.increment = function(){
      self.counter(self.counter() + 1);  
    };
}
var vm = new AppViewModel();
vm.getFakeData();   // replace with getData()
ko.applyBindings(vm);
</script>

小提琴,带有示例数据的 getFakeData:https://jsfiddle.net/4hxyarLa/1/

如果要有很多行并且关注内存,则可以将增量函数放在 AppRecord 的原型方法中,并通过函数上的参数访问记录,或者可以将函数添加到 AppViewModel 并绑定到 $parent.increment 以调用它,并通过传递给该函数的参数访问记录以递增其计数器属性。