web-dev-qa-db-ja.com

knockoutjsで特定のインデックス要素を置き換える方法

ObservableArray内の特定のインデックスを別の要素に置き換えるにはどうすればよいですか。

私は持っています:ViewModel.Elements()[index]

どうすれば別の要素に置き換えることができますか。

24
user656822

observableArraysにはreplaceメソッドがあります。これは、古いアイテムと新しいアイテムを取り込みます。

だから、あなたはそれを次のように呼ぶでしょう:

ViewModel.Elements.replace(ViewModel.Elements()[index], yourNewElement);

内部的には、これはそのインデックスを新しいアイテムに設定し、valueHasMutated()を呼び出して潜在的なサブスクライバーに通知します。

38
RP Niemeyer

今では少し遅れていますが、この質問にはまだ(適切に)答えられていないことに気づきました。

他の人が述べているように、最初の答えは期待される動作を与えません。それはobservableArrayのアイテムをvalueではなくindexに置き換えます!

他の答えは非常に複雑で、ノックアウトの拡張ネイティブを利用していません。


indexの特定のobservableArrayの値を真に置き換えるには、splice()メソッドを使用する必要があります。

_var myObservable = ko.observableArray([1, 2, 3, 4]);
myObservable.splice(0, 1, 100); // Replace the value at [0] with "100"
myObservable.splice(2, 1, 300); // Replace the value at [2] with "300"
console.log(myObservable()); // [100, 2, 300, 4]
_

また、splice()メソッドはKnockoutによって拡張されているため、依存関係を自動的に通知し、valueHasMutated()を呼び出す必要がなくなります。

編集/ 2016年2月14日

一度に複数の値を置き換える必要がある場合は、基になる配列を取得し、置き換えを実行してから、変更を通知する方がはるかに高速です。

_var myObservable = ko.observableArray([1, 2, 3, 4]);
var underlyingArray = myObservable();

myObservable.valueWillMutate();

for(...)
   underlyingArray[i] = newValue[i];

this.valueHasMutated();
_
10
losnir

Dvijazが正しく指摘しているように、受け入れられた回答は指定された値を置き換えます。これは、指定された値が配列内で一意でない場合に問題を引き起こす可能性があります。

配列をスライスしてから接着して戻す代わりに、私は次のことを行いました。これは私見です。

ViewModel.Elements()[index] = yourNewElement;
ViewModel.Elements.valueHasMutated();

方法を指摘してくれたRPNiemeyerに感謝します.replace内部で機能します。

これをサポートするためにobservableArrayを拡張することもできます。

ko.observableArray.fn.replaceIndex = function(index, newValue) {
    this.valueWillMutate();
    this()[index] = newValue;
    this.valueHasMutated();
};

つまり、次のことができます。

var arr = ko.observableArray([1, 2, 1, 4]);
arr.replaceIndex(2, 3); 
console.log(arr()); // logs [1, 2, 3, 4]
5
sroes

質問は、特定の値ではなく、「特定のインデックス」を置き換える方法を尋ねます。受け入れられた回答は、observableArrayに繰り返しがない場合に機能しますが、繰り返しがある場合は、常に期待どおりに動作するとは限りません。例えば。私たちが持っていると仮定します:

index = 2;
elements = ko.observableArray([9,8,9]);

次に、受け入れられた回答を使用します。

elements.replace(elements()[index], 7);

その場合、elements[7,8,9]になります(replaceindexOfを使用するため、指定された値9の最小のインデックスを検索します)が、質問は確かにelements[9,8,7]にするソリューションを期待しています。

ObservableArray newElementindexにあるアイテムをelementsに本当に置き換えるには、次を使用できます。

elements(elements.slice(0, index).concat(newElement, elements.slice(index + 1)));

もっとエレガントなものはニースでしょう。 IIUCですが、パフォーマンスではなく読みやすさの問題です。

4
Jonathan

基になる配列を編集して再割り当てすることで、私はうまくいきました。私は他のアプローチで問題を抱えていました。

var underlyingArray = this.someObservableArray();

// Do modifications... Swap some items...
// No one is being notified just yet...

// Reassign to observable to update everything
this.someObservableArray(underlyingArray);
0
Timo