Javascript 通过索引KnockoutJS写入的可观察数组

Javascript 通过索引KnockoutJS写入的可观察数组,javascript,knockout.js,frontend,Javascript,Knockout.js,Frontend,我无法通过特定索引写入可观察数组 JS HTML页面 <input type="number" data-bind="value: curNumber"> <button data-bind="click: addNumber">Add</button> 添加 我希望当我在输入上写“1”并单击“添加”按钮时,第一个索引值将在1上递增,但它对我不起作用 function AppViewModel() { this.curNumber = ko.ob

我无法通过特定索引写入可观察数组 JS

HTML页面

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

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

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.observearray
包含一个香草Javascript数组作为值,因此需要使用
this.numbers()[index]
提取Javascript香草,注意
()
,打开ko.observearray值并返回该值,即Javascript数组

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

最后,使用@Kenneth的答案,您需要让KnockoutJs知道,如果您的UI或其他观察对象要通过调用
this.numbers
来响应您的
addNumber
调用,那么ko.observearray已经发生了变化

最好在可观察的
curNumber
上使用
subscribe
来监听
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();
    });
}
如果它适合您的需要,下面是一个使用KnockoutJS
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();
    });
}
现在您不需要调用
addNumber
的额外步骤

下面只是对valueHasMutated的测试,我反复检查了提取Javascript数组和更新数组中的项目是否是KnockoutJs无法观察到的,在这种情况下,您必须调用valueHasMutated(),否则KnockoutJs将不会注意到您的数组增量

函数AppViewModel()
{
this.curNumber=ko.可观察(0);
this.numbers=ko.observearray([0,0,0,0,0,0,0]);
this.addNumber=函数(){
resetUI();
this.numbers()[this.curNumber()]++;
this.numbers.valueHasMutated();
}
this.addNumberWithoutHasValueMutated=函数(){
resetUI();
this.numbers()[this.curNumber()]++;
}
this.numbers.subscribe(函数(newValue){
$('#divStatus').html(“true”);
});
}
var viewModel=新的AppViewModel();
应用绑定(视图模型);
函数resetUI(){
$('#divStatus').html(“false”);
}

通过敲除观察阵列变化:
假的

这是"数字"()=
这个.curNumber()=

呼叫地址号码


调用addnumberwhithouthasvaluemutated
正如Brian在回答中所说,数组是可观察的,但数组中的值不是。如果要触发更新,必须通过在可观察对象上调用
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());

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

您的代码:

this.numbers[this.curNumber]++
有几个问题:

问题1:
this.curNumber
是一个可观察值,必须将其作为函数调用,才能将值包装在其中

问题2 即使这样做,它仍然无法工作,因为从DOM获得的值是一个字符串,因此需要首先将其转换为数字

var index = Number(this.curNumber());
问题3
this.numbers
不是一个数组,它是一个
observearray
。你不能直接索引到它

选项1 手动进入数组,然后通知值已更改(本质上)

选项2 拼接

splice
方法在
observableArray
上实现,其行为与之完全相同,并且它将自动通知订阅者

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

array.splice(index, 1, newItem);
这意味着:从位置
索引
中取出一个项目,并将其放入
新项目

因此,在你的情况下:

this.addNumber = function() {
    var index = Number(this.curNumber());
    var newValue = this.numbers()[index] + 1;
    this.numbers.splice(index, 1, newValue);
}
在JSFIDLE上查看它:


我不熟悉knockout.js,但是
this.addNumber
函数中的索引应该是
this.curNumber
而不是
curNumber
?@jason kennaly,感谢您的快速响应。谢谢你的快速回复。我修好了第一根柱子。但我仍然有这个问题虽然这是有价值的输入,但它并没有真正回答问题Hi@Kenneth,我的答案与你的addNumber函数的函数实现相同,区别在于你调用的是valueHasMutated,但是ko.indexOf应该返回一个可观察的,我不确定你是否需要调用valueHasMutated,我认为应该通过敲除来“观察”增量不,它不是。indexOf只返回第一个匹配项的索引。无论你以后用那个值做什么,敲除都不会观察到。事实上,它的编写方式甚至不会增加值。它只会得到索引,然后递增并丢弃。这不是:this.numbers()[this.curNumber()]++;比您的答案可读性更强,parseInt很好,但也不是真正需要的,curNumber无论如何都不应该初始化为类似OP代码的字符串。此外,还需要调用valueHasMutated(),正如@Kenneth在其回答中指出的,无论您说什么。对于一个简单的问题,我真的没有时间阅读这么多的文本。检查一下我的小提琴。你不需要valueMutated。说话就像某人无缘无故地写那么长一行代码一样。是的,如果你想让KnockoutJS观察UI或其他观察对象中的变化,你需要这样做,这有点像KnockoutJS
array.splice(index, 1, newItem);
this.addNumber = function() {
    var index = Number(this.curNumber());
    var newValue = this.numbers()[index] + 1;
    this.numbers.splice(index, 1, newValue);
}