按索引 KnockoutJS 写入的可观察数组
Observable arrays write by index KnockoutJS
我无法通过特定索引写入可观察数组
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”并单击“添加”按钮时,第一个索引值将递增 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());
A ko.observableArray
包含原版 Javascript 数组作为值,因此您需要使用 this.numbers()[index]
提取 Javascript 原版数组,注意 ()
,解包ko.observableArray 值和 returns 该值,一个 Javascript 数组。
在您的代码中,您试图对 ko.observableArray 本身进行数组索引:this.numbers[index]
最后,使用@Kenneth 的回答,如果您的 UI 或其他可观察对象要对您的 addNumber
调用做出反应,您需要让 KnockoutJs 知道 ko.observableArray 已经发生变化,也就是发生了变化在 this.numbers
.
上调用 valueHasMutated
最好在 curNumber
observable 上使用 subscribe
来监听 curNumber
的变化,并且 subscribe
函数每次都会自动触发你的增量curNumber
变化。
如果适合您的需要,这里是使用 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
忽略
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");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>Array change is observed by Knockout: </label>
<span id="divStatus" style="color: red;">false</span>
<br />
<label>this.numbers() =</label>
<span data-bind="text: numbers()"></span>
<br />
<label>this.curNumber() =</label>
<input type="number" data-bind="value: curNumber" />
<br />
<br />
<button class="reset" data-bind="click: addNumber">Call AddNumber</button>
<br />
<br />
<button class="reset" data-bind="click: addNumberWithoutHasValueMutated">Call AddNumberWithoutHasValueMutated</button>
正如 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());
使用此代码,检查 fiddle: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;
}
您的代码:
this.numbers[this.curNumber]++
有几个问题:
问题 #1:
this.curNumber
是一个 observable,您必须将它作为一个函数来调用以获取包含在其中的值。
问题 #2
即使你这样做,它仍然不会起作用,因为你从 DOM 得到的值是一个字符串,所以你需要先将它转换为一个数字。
var index = Number(this.curNumber());
问题 #3
this.numbers
不是数组,它是一个 observableArray
。你不能直接索引它。
选项 #1
手动进入数组,然后通知值已更改(本质上是)
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 上查看:
我无法通过特定索引写入可观察数组 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”并单击“添加”按钮时,第一个索引值将递增 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());
A ko.observableArray
包含原版 Javascript 数组作为值,因此您需要使用 this.numbers()[index]
提取 Javascript 原版数组,注意 ()
,解包ko.observableArray 值和 returns 该值,一个 Javascript 数组。
在您的代码中,您试图对 ko.observableArray 本身进行数组索引:this.numbers[index]
最后,使用@Kenneth 的回答,如果您的 UI 或其他可观察对象要对您的 addNumber
调用做出反应,您需要让 KnockoutJs 知道 ko.observableArray 已经发生变化,也就是发生了变化在 this.numbers
.
valueHasMutated
最好在 curNumber
observable 上使用 subscribe
来监听 curNumber
的变化,并且 subscribe
函数每次都会自动触发你的增量curNumber
变化。
如果适合您的需要,这里是使用 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
忽略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");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>Array change is observed by Knockout: </label>
<span id="divStatus" style="color: red;">false</span>
<br />
<label>this.numbers() =</label>
<span data-bind="text: numbers()"></span>
<br />
<label>this.curNumber() =</label>
<input type="number" data-bind="value: curNumber" />
<br />
<br />
<button class="reset" data-bind="click: addNumber">Call AddNumber</button>
<br />
<br />
<button class="reset" data-bind="click: addNumberWithoutHasValueMutated">Call AddNumberWithoutHasValueMutated</button>
正如 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());
使用此代码,检查 fiddle: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;
}
您的代码:
this.numbers[this.curNumber]++
有几个问题:
问题 #1:
this.curNumber
是一个 observable,您必须将它作为一个函数来调用以获取包含在其中的值。
问题 #2
即使你这样做,它仍然不会起作用,因为你从 DOM 得到的值是一个字符串,所以你需要先将它转换为一个数字。
var index = Number(this.curNumber());
问题 #3
this.numbers
不是数组,它是一个 observableArray
。你不能直接索引它。
选项 #1
手动进入数组,然后通知值已更改(本质上是
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 上查看: