可观察数组按索引KnockoutJS

时间:2016-01-17 23:01:27

标签: javascript knockout.js frontend

我遇到了通过特定索引写入可观察数组的问题 JS

function AppViewModel()
{
this.curNumber = ko.observable("");
this.numbers = ko.observableArray([0,0,0,0,0,0,0,0,0]);
this.addNumber = function() { this.numbers[this.curNumber]++;}
}
ko.applyBindings(new AppViewModel());

HTML页

<input type="number" data-bind="value: curNumber">
<button data-bind="click: addNumber">Add</button>

我希望当我在输入上写入“1”并单击“添加”按钮时,第一个索引值将增加一个,但它对我不起作用

4 个答案:

答案 0 :(得分:0)

function AppViewModel()
{
    this.curNumber = ko.observable();
    this.numbers = ko.observableArray([0,0,0,0,0,0,0,0,0]);
    this.addNumber = function() { 
        this.numbers()[this.curNumber()]++;
        this.numbers.valueHasMutated();
    }
}

ko.applyBindings(new AppViewModel());

ko.observableArray包含一个vanilla Javascript数组作为值,因此您需要使用this.numbers()[index]提取Javascript vanilla,注意(),解包ko.observableArray值并返回该值,一个Javascript数组。

在你的代码中,你试图对ko.observableArray本身进行数组索引:this.numbers[index]

最后,使用@Kenneth的答案,你需要让KnockoutJs知道ko.observableArray已经变异,如果你的UI或其他可观察者通过调用{{addNumber来对你的valueHasMutated调用作出反应1}} this.numbers

最好在subscribe observable上使用curNumber来监听curNumber的更改,而subscribe函数每次都会自动触发您的增量{{ 1}}改变。

如果它符合您的需求,以下是使用KnockoutJS curNumber并且每次subscribe更改时的实现。

curNumber

现在您不需要调用function AppViewModel() { this.curNumber = ko.observable(); this.numbers = ko.observableArray([0,0,0,0,0,0,0,0,0]); this.curNumber.subscribe(function(newValue) { this.numbers()[newValue]++; this.numbers.valueHasMutated(); }); } 的其他步骤。

下面只是对valueHasMutated的测试,我是双重检查提取Javascript数组并更新数组中的项目将是KnockoutJs不会观察到的事情,情况就是这样,你必须调用valueHasMutated(或者你的数组增量将被KnockoutJs

忽视

&#13;
&#13;
addNumber
&#13;
function AppViewModel()
{
  this.curNumber = ko.observable(0);
  this.numbers = ko.observableArray([0,0,0,0,0,0,0,0,0]);
  this.addNumber = function() { 
     resetUI();
     this.numbers()[this.curNumber()]++;
     this.numbers.valueHasMutated();
  }
  
  this.addNumberWithoutHasValueMutated = function() {
     resetUI();
     this.numbers()[this.curNumber()]++;
  }

  this.numbers.subscribe(function(newValue) {
     $('#divStatus').html("true");
  });
}

var viewModel = new AppViewModel(); 
ko.applyBindings(viewModel);

function resetUI() {
  $('#divStatus').html("false");
}
&#13;
&#13;
&#13;

答案 1 :(得分:0)

正如Brian在他的回答中所说的那样,数组是可观察的,但数组中的值不是。如果要触发更新,则必须通过调用observable上的valueHasMutated手动执行此操作:

function AppViewModel()
{
    this.curNumber = ko.observable("");
    this.numbers = ko.observableArray([0,0,0,0,0,0,0,0,0]);
    this.addNumber = function() { 
        var index = this.curNumber();
        var arr = this.numbers();
        arr[index] = arr[index] + 1;
        this.numbers.valueHasMutated(); // This tells knockout the value has changed
    }
}

ko.applyBindings(new AppViewModel());

答案 2 :(得分:0)

使用此代码,请检查小提琴:Fiddle

this.curNumber = ko.observable("");
this.numbers = ko.observableArray([0,0,0,0,0,0,0,0,0]);
this.addNumber = function() { 
            this.numbers()[parseInt(this.curNumber())] = this.numbers()[parseInt(this.curNumber())]+1;
}

答案 3 :(得分:0)

您的代码:

this.numbers[this.curNumber]++

有几个问题:

问题#1:

this.curNumber是一个可观察的,您必须将其称为函数以获取包含在其中的值。

问题#2

即使你这样做,它仍然无法工作,因为你从DOM获得的值是一个字符串,所以你需要先将它转换为数字。

var index = Number(this.curNumber());

问题#3

this.numbers不是数组,而是observableArray。你不能直接索引它。

选项#1

手动进入数组,然后通知该值已更改(基本上为Kenneth's answer

this.numbers()[index]++;
this.numbers.valueHasMutated();

选项#2

通联!

splice方法在observableArray上实施,其行为与the splice method on vanilla JS Arrays完全相同,而且会自动通知订阅者。

您可以使用它以这种方式在特定索引上放置新项目:

array.splice(index, 1, newItem);

这意味着:从位置index中取出一个项目并放入其中newItem

所以在你的情况下:

this.addNumber = function() {
    var index = Number(this.curNumber());
    var newValue = this.numbers()[index] + 1;
    this.numbers.splice(index, 1, newValue);
}

在jsfiddle上查看:

https://jsfiddle.net/czfpbtbv/1